Java - 并发

阅读数:164 评论数:0

跳转到新版页面

分类

python/Java

正文

一、创建线程

创建线程有四种方式:继承Thread类、实现Runnable接口、实现Callable接口、通过线程池创建。

1、继承Thread

重写run方法。

class A extends Thread{
function1;
function2;
...
public void run(){
//other code...
}
property1;
property2;
}

(1)常用方法

start方法 用于启动一个线程。
sleep方法 如果调用了sleep方法,必须捕获InterruptedException异常或者将该异常向上层抛出,sleep方法不会释放该线程所拥有的资源。
join方法

当前线程调用其它线程的join方法,会阻塞当前线程,直到其他线程执行完毕。

join方法是被Synchronized关键字所修饰的,如果有两个线程同时调用另外一个线程的join方法,会有一个线程成功得到锁,而另外一个必须等待。

yield方法  此方法会让当前线程进入就绪状态,交出cpu资源,让cpu去执行其他的线程。
class JoinThread implements Runnable
{

    //重写run方法
    public void run()
    {
        for(int i = 0; i< 30;i++)
        {
            System.out.println(Thread.currentThread().getName()+"..."+i);
        }

    }

}

//main方法如下
public static void main(String[] args) throws InterruptedException
    {

        JoinThread object = new JoinThread();

        Thread t1 = new Thread(object);

        Thread t2 = new Thread(object);


        t1.start();
        t1.join();

        t2.start();

        for(int j = 0;j < 50;j++)
        {
            System.out.println(Thread.currentThread().getName()+"..."+j);
        }



    }

2、实现Runnable接口

实现Runnable接口并编写run方法。

class B implements Runnable{
function1;
function2;
...
public void run(){
//other code...
}
property1;
property2;
...
}

3、实现Callable接口

与Runnable的不同:

(1)它有返回值

(2)执行方法名为call()

class myCall implements Callable<Integer> {
  @Override
  public Integer call() throws Exception {
    //
    return 1024;
  }
}

二、Object中相关的并发控制方法

wait 将当前线程放入object对象的等待队列中。
notify 从object的等待队列中唤醒一个线程。
notifyAll  唤醒object的等待队列中的所有线程。

三、Runtime类

Runtime类封装了运行时的环境每个Java应用程序都有一个Runtime类实例,使用应用程序能够与其运行环境相连接。通过Runtime.getRuntime()获取Runtime类的实例。Runtime类使用的是单例模式。

1、Runtime.getRuntime().addShutdownHook

这个方法的意思就是在jvm中增加一个关闭的钩子,当jvm关闭的时候,会执行系统中已经设置的所有通过这个方法添加的钩子,当系统执行完这些钩子后,jvm才会关闭。所以这些钩子可以在jvm关闭的时候进行内存清理、对象销毁等操作。

四、java.util.concurrent包

Java 5添加了一个新的包到Java平台,java.util.concurrnet包。这个包包含有一系列能够让Java的并发编程变得更加简单轻松的类。

1、BlockingQueue(接口) 阻塞队列

一个线程将会持续生产新对象并将其插入到队列之中,直到队列达到它所能容纳的临界点。也就是说,它是有限的,如果该阻塞队列到达了其临界点,负责生产的线程将会在往里面插入新对象时发生阻塞。

负责消费的线程将会一直从该阻塞队列中拿出对象。如果消费线程尝试去从一个空的队列中提取对象的时候,这个消费线程将会处于阻塞中,直到一个生产线程把一个对象丢进队列。

BlockingQueue是个接口,你需要使用它的实现之一使用BlockingQueue

ArrayBlockingQueue 是一个有界的阻塞队列
DelayQueue 对元素进行持有直到一个特定的延迟到期,注入其中的元素必须实现 java.util.concurrnet.Delayed接口。
LinkedBlockingQueue 可以选择一个上限
PriorityBlockingQueue 无界队列,所有插入到PriorityBlockingQueue的元素必须实现java.lang.Comparable接口
SynchronousQueue  它的内部同时只能容纳单个元素。

2、BlockingDeque(接口) 阻塞双端队列

双端队列是一个你可以从任意一端插入或提取元素的队列。这也是一个接口,它的实现类有LinkedBlockingDeque

3、ConcurrentMap(接口) 并发Map

这是一个接口,其实现类为ConcurrentHashMap

(1)ConcurrentHashMap

putIfAbsent方法  在key不存在的时候加一个值,如果key存在就不放入。

4、CountDownLatch 闭锁

它允许一个或多个线程等待一系列指定操作的完成。

CountDownLatch以一个给定的数量初始化。countDown()每被调用一次,这一数量就减一。通过调用await()方法,线程可以阻塞等待这一数量到达零。

5、CyclicBarrier(栅栏)

这是一个同步机制,它能够处理一些算法的线程的同步问题。换句话说它就是一个所有线程必须等待的一栅栏,直到所有的线程都到达这里,然后所有线程才可以继续做其他事情。

6、Exchanger

表示一种两个线程可以进行互相交换对象的点。

7、Semaphore信息量

(1)acquire()

(2)release()

信号量主要有两种用途:

(1)保护一个重要的(代码)部分防止超过N个线程进入。

(2)在两个线程之间发送信号

8、ExecutorService(接口)

类似于一个线程池。这是一个接口,它的实现类有ThreadPoolExecutor和ScheduledThreadPoolExecutor。

ThreadPoolExecutor包含的线程池的数量由下面变量决定:

(1)corePoolSize

(2)maximumPoolSize

当一个任务委托给线程池时,如果线程数理低于corePoolSize,一个新的线程将被创建,即使池中可能尚有空闲线程。

如果内部 任务队列已满,而且有至少corePoolSize正在运行,但是运行线程的数量低于maximumPoolSize,一个新的线程将被创建。

9、ForkJoinPool

在Java7中被引入,这是一个特殊的线程池,它的设计是为更好的配合分叉-合并任务的工作。

10、Lock (接口)锁

它是一个类似于synchronized块的线程同步机制。但是Lock比synchronized块更加灵活、精细。

(1)synchroinzed代码块不能够保证进入访问等待的线程的先后顺序。

(2)不能够传递任何参数给一个synchronized代码块的入口

(3)synchronized块必须被完整地包含在单个方法里,而一个Lock对象的可以把它的lock和unlock方法的调用放在不同的方法里。

这是一个接口,它的实现类是ReetrantLock

11、ReadWriteLock读定锁

它能够允许多个线程在同一时间对某特定资源进行读取,但同一时间内只有一个线程对其进行写入。这是一个接口,它的实现类是ReentrantReadWriteLock。

12、原子变量

AtomicBoolean  
AtomicInteger  
AtomicLong  
AtomicReference  
get() 返回当前的引用。
compareAndSet(expect, update) 如果当前值与给定的expect相等(是引用相等),更新为指定的update值。
getAndSet(newValue)  原子地设为给定值并返回旧值。

13、ConcurrentNavigableMap

heapMap(T toKey) 返回一个包含小于给定toKey的key的子map。
ailMap(T fromKey) 返回一个包含了不小于给定fromKey的key的子map。
subMap(T from,T to)  返回一个键值介于from(包含)和to(不包含)之间的子map。

14、ConcurrentLinkedDequeue

Java 7中引入的类,它实现了一个非阻塞并发列表,如果操作不能立即完成,会抛出异常或者返回一个null值。

(1)getFirst()和getLast()这些方法返回分别从列表中第一个和最后一个元素。他们不会从列表中删除返回的元素。如果列表是空的,这些方法抛出一个NoSuchElementException。

(2)peek(),peekFirst(),peekLast()这些方法返回列的第一个和最后一个元素。他们不会从列表中删除返回的元素。如果列表为空,这些方法返回一个null值。

(3)remove(), removeFirst(), removeLast():这此方法返回列表的第一个和最后一个元素。他们从列表中移除返回的元素。如果列表是空的,这些方法抛出一个NoSuchElementException。

(4)像大多数其他并发集合类实现,这个类不允许null元素的使用。

15、CopyOnWrite

从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayListCopyOnWriteArraySet

读的时候不需要加锁,如果读的时候有多个线程正在向CopyOnWriteArrayList添加数据,读还是会读到旧的数据,因为写的时候不会锁住旧的CopyOnWriteArrayList。

CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性,所以如果你希望写入的数据,马上能读到,请不要使用CopyOnWrite容器。




相关推荐

1、Runnable 因为Java单继承,所以相对于继承Thread类,实现Runnable接口要更好。 <cod

如果一个线程处于了阻塞状态(如线程调用了thread.sleep、thread.join、thread.wait、1.5中的condition.await、以及可中断的通道上的 I/O 操作方法

一、概述 早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程

原因: view控件不是线程安全的,所以更新UI操作都必须在UI线程中完成,而不能在非UI线程中。 解决方法: 使用Handler,其实每个线程

在JDK标准版5中,由DougLea 提供的并行框架成为了标准库的一部分(JSR-166)。随后,在JDK6中,一些新的并行特殊,例如并行collection框架,合并到标准库中。 <p

class SimpleThreadFactory implements ThreadFactory { public Thr

一、概述 1、两种类加载方式的选择 前者是最安全的方法。 比如,如果你使用Test.class.getClassLoader(),可能会导制和当前线程所运行的类加载器不一致。(因为Java是多线程的)

一、概述 在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景。 阻塞队列提供了四种处理方法: 方法\处理方式 抛出异常

一、异常之间的关系 1、Error Error是Throwable的子类,代指应用程序不应该试图捕获的严重问题。 2、Exception 代指应用程序应该捕获的异常。分为未检查异常(RuntimeE

java中的daemon thread java中有两种类型的thread,user threads 和 daemon threads。 User threads是高