通过学习《Thinking in Java》,总结并发API如下:

12.1 Thread.yield():说明自己用的cpu时间差不多了,可以让别的线程使用cpu了,不一定会被采纳,就是说别的线程不一定就会马上获得cpu

12.2 线程池有固定大小,不固定大小的(newCachedThreadPool建议使用这个),以及单线程(newSingleThreadExecutor即只能一个线程结束后,第二个线程才执行)的。shutdown():不接受新任务

12.3 后台线程daemon:t.setDaemon(true) 需在t.start()之前设定,其创建的所有线程都为后台线程。当非后台线程都停止时,后台线程会立刻终止,finally子句不会执行;

12.4 Runnable任务:class可以implements Runnable()。之后其class可以用线程池调度:

ExecutorService exec = Executors.newCachedThreadPool();
     exec.execute(new class());

    也可以用Thread t = new Thread(new classA());

12.5 join()方法:可以理解为等待其他线程结束再开始执行自己,如在t1线程中调用t2.join(),则t1要等待完t2结束才能往下执行

12.6 异常:Interupted异常能被自己捕获,但调用isInterrupted()方法时为false

     run本身不能捕获运行时异常,需用UncaughtExceptionHandler捕获,例子如下:

 

package JavaBase2;
 
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class ExceptionThread {
    public static void main(String[] a){
        //ExecutorService exe = Executors.newCachedThreadPool(new HandlerThreadFactory());
        //ExecutorService exe = Executors.newCachedThreadPool();
        //System.out.println(new ExceptionThread());
        ExecutorService exe = MySys.getExe();
        exe.execute(new ExceptionThread2());
    }
 
 
}
 
class ExceptionThread2 implements Runnable{
 
    public void run(){
        Thread t = Thread.currentThread();
        System.out.println("run by thread " + t.getName());
        System.out.println("eh=" + t.getUncaughtExceptionHandler());
        //throw new RuntimeException();
        MySys.callExceptionMethod();
    }
}
 
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{
 
    public void uncaughtException(Thread t,Throwable e){
        System.out.println("caught " + e);
        ExecutorService exe = MySys.getExe();
        exe.execute(new NormalThread());
        exe.execute(new NormalThread());
 
    }
}
 
class HandlerThreadFactory implements ThreadFactory{
 
    public Thread newThread(Runnable r){
        System.out.println(this + " create new Thread");
        Thread t = new Thread(r);
        System.out.println("created " + t);
        t.setUncaughtExceptionHandler(MySys.getEh());
        System.out.println("eh=" + t.getUncaughtExceptionHandler());
        return t;
 
    }
 
}
 
class NormalThread implements Runnable{
    public void run(){
        Thread t = Thread.currentThread();
        System.out.println("new a normal thread=" + t.getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
        System.out.println("sleep end....");
    }
}
 
class MySys{
    //private static ExecutorService exe = Executors.newSingleThreadExecutor(new HandlerThreadFactory());
    private static ExecutorService exe = Executors.newCachedThreadPool(new HandlerThreadFactory());
    private static MyUncaughtExceptionHandler eh = new MyUncaughtExceptionHandler();
    public static ExecutorService getExe(){
        return exe;
    }
    public static MyUncaughtExceptionHandler getEh(){
        return eh;
    }    
 
    public static void callExceptionMethod(){
        System.out.println("Exception method run.....");
        throw new RuntimeException();
    }
}

 

 

12.7 volatile的使用:保证工作线程从jvm内存拿到的值是最新的;也就是确保有可视性,即主内存的值修改后,马上对全部工作线程可见,全部工作线程内存的值再次使用时会到主内存读取。java的64位操作可能有字撕裂。但不是线程安全的,详见:

12.8 synchronized:锁住共享资源,其一般表现为对象锁,即锁住对象形式存在的内存片段。一个对象一把锁,多个synchronized共用一把锁,一个对象的多个synchronized是互斥的。对于读和写的共享资源都要加锁

        一个任务可以获得对象的多个锁,即调用多个synchronized片段,采用计数器计数,当为0时说明调用完成。

        类也可以有synchronized,synchronized static

        同步块比同步方法性能更优

        同步块须给定一个对象上锁,一般是this,锁住当前对象,当前对象的其他临界资源也被锁住

        如果在一个对象上有两个同步锁,其加锁的对象一个是当期对象,一个是其他对象,则这两个同步锁不会互斥

        

12.9 显式锁:进出的时候加锁解锁,解锁在return之后:

   

private int count = 0;
        private Lock lock=new ReentrantLock();
        public int next(){
            try{
                lock.lock();                ++count;
                Thread.yield();    
                ++count;
                return count;
            }finally{
                lock.unlock();
             }

 12.10 原子性:应用于除long和double之外的所有基本类型之上的“简单操作”,也就是赋值和返回值。            

 12.11 中断:I/O和synchronized是不可中断的,除非中断其依赖的底层资源,sleep可以直接用ExectorServicce.submit().cancel(true)中断;

12.12  在构造器中锁了自己,其他任务通过自身的引用也会互斥:

 

android 并发执行 并发api_System

12.13 ExectorService exec = Executors.newCachedThreadPool();

            exec.shutdownNow();//调用所有由他控制的线程的interrupt();

12.14 wait():是Object的方法,释放锁,相当于挂起(而sleep不会释放锁),可以用notify()和notifyAll()   唤醒,也可以等时间到期唤醒。只能在同步块中使用,否则会报运行异常,因为使用者需获得锁。

 12.15 notify():唤醒等待锁的某个任务,notifyAll()唤醒等待锁的全部任务,而且只是唤醒等待同一个对象锁的全部任务,等待不同对象锁的任务不会唤醒;

12.16 List<L> data = Collections.synchronizedList(new ArrayList<L>): data的所有方法都是线程安全的。

12.17 Semaphore:控制多个任务访问共享资源

12.18 ExecutorService exec = Executors.newCachedThreadPool();

          线程的run方法的while用:

public void run(){ 
try{
         while(!Thread.interrupted()){}
  }catch{  }

 

当调用exec.shutdownNow()时,可以终止while循环

 

12.20 CoutDownLatch:一种用来等待一组任务完成,其他任务才能执行的锁

        CountDownLatch latch = new CountDownLatch(100);

    如果A调用了latch.await();

    B1调用了latch.countDown();

    B2调用了latch.countDown();

    ........................B100调用了latch.countDown();即减到了0;A任务才能往下走

 

12.21 CyclicBarrier:与CountDownLatch类似,不同的是其可以循环计数。

12.22 AtomicLong,Lock,synchronized比较:优先使用syn锁,因为可读性好;计数器用Atomic。

12.23 免锁容器CopyOnwriteArrayList:读写可同时进行,修改时有副本,当修改完成时一个原子性操作修改原来的容器,不会抛出ConcurrentModificationException。

12.24 读写锁ReadWriteLock,读要等写完才能读,多个读不互斥。当写锁被其他任务持有时,任何读取者都不能访问,直到写锁释放为止。

12.25 乐观锁,atomic.compareAndSet(oldvalue,newvalue),更新时如新值不等于旧值会失败。

12.26 延迟队列DelayQueue,延迟到期才能从队列取走。延迟最多最后执行,用CompareTo方法比较顺序。Comparable可以使用范型。

12.17 优先队列PriorityBlockingQueue,也是基于Comparable,排在前面的优先级最高先执行,与延迟相反。