并发知识点札记

首先需要明确的是:多线程开发并不等于高并发解决方案。

1.线程池:ThreadPoolExecutor

import java.util.concurrent.BlockingQueue;  
import java.util.concurrent.LinkedBlockingQueue;  
import java.util.concurrent.ThreadPoolExecutor;  
import java.util.concurrent.TimeUnit;  


public class ThreadPoolTest implements Runnable {
        
     public void run() {   
          synchronized(this) {   
            try{  
                System.out.println(Thread.currentThread().getName());  
                Thread.sleep(3000);  
            }catch (InterruptedException e){  
                e.printStackTrace();  
            }  
          }   
     }   

     public static void main(String[] args) {   
         BlockingQueue queue = new LinkedBlockingQueue();  
         ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 6, 1, TimeUnit.DAYS, queue);  
         for (int i = 0; i < 10; i++) {     
             executor.execute(new Thread(new ThreadPoolTest(), "TestThread".concat(""+i)));     
             int threadSize = queue.size();  
             System.out.println("线程队列大小为-->"+threadSize);  
         }     
         executor.shutdown();    
     }  
}   

例子参见http://blog.csdn.net/shixing_11/article/details/7109471
2.synchronized VS Volatile
for example:
二话不说,代码如下:

public class VisibilityTest extends Thread {
     
    private  boolean stop;

    public void run() {
        int i = 0;
        while(!stop) {
            i++;
        }
        System.out.println("finish loop,i=" + i);
    }

    public void stopIt() {
        stop = true;
    }

    public boolean getStop(){
        return stop;
    }
    public static void main(String[] args) throws Exception {
        VisibilityTest v = new VisibilityTest();
        v.start();

        Thread.sleep(1000);
        v.stopIt();
        Thread.sleep(2000);
        System.out.println("finish main");
        System.out.println(v.getStop());
    }
}

在hotspot中,如果是在控制台中运行,可分别尝试下面两种方式:
1、java VisibilityTest
2、java -server VisibilityTest
如果是在eclipse中,可以右键-Run As-Run Configuration-Arguments标签-VM arguments中填入-server
因为线程安全问题在-server模式下会死循环!
然后可以讲private boolean stop修改成private volatile boolean stop再看效果。
更多-client和-server的信息,以及何时会默认使用-server,何时会默认使用-client,请百度。由此看到,编写多线程程序时,线程安全之重要。

例子摘自:http://www.ticmy.com/?p=5

3.ReentrantLock VS Synchronized
关于这两者的对比网上的解释很多,大体就是(抛砖引玉下):
ReentrantLock在构造方法的时候可以设置公平锁和非公平锁,两者效率不一样,应用也场景不一样;
ReentrantLock需要显示地开启和关闭;
ReentrantLock是类级别的锁机制,Synchronized属于JVM级别的;
ReentrantLock可以更加灵活的控制线程,可以让一直等不到资源的线程自己退出,避免死等。
4.CountDownLatch
一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行
for example:

public class CountDownLatchTest {

    // 模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。
    public static void main(String[] args) throws InterruptedException {

        // 开始的倒数锁 
        final CountDownLatch begin = new CountDownLatch(1);  

        // 结束的倒数锁 
        final CountDownLatch end = new CountDownLatch(10);  

        // 十名选手 
        final ExecutorService exec = Executors.newFixedThreadPool(10);  

        for (int index = 0; index < 10; index++) {
            final int NO = index + 1;  
            Runnable run = new Runnable() {
                public void run() {  
                    try {  
                        // 如果当前计数为零,则此方法立即返回。
                        // 等待
                        begin.await();  
                        Thread.sleep((long) (Math.random() * 10000));  
                        System.out.println("No." + NO + " arrived");  
                    } catch (InterruptedException e) {  
                    } finally {  
                        // 每个选手到达终点时,end就减一
                        end.countDown();
                    }  
                }  
            };  
            exec.submit(run);
        }  
        System.out.println("Game Start");  
        // begin减一,开始游戏
        begin.countDown();  
        // 等待end变为0,即所有选手到达终点
        end.await();  
        System.out.println("Game Over");  
        exec.shutdown();  
    }
}

上面例子转载地址:http://www.itzhai.com/the-introduction-and-use-of-a-countdownlatch.html
5.CyclicBarrier VS CountDownLatch
CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。 CyclicBarrier : N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。
这样应该就清楚一点了,对于CountDownLatch来说,重点是那个“一个线程”, 是它在等待, 而另外那N的线程在把“某个事情”做完之后可以继续等待,可以终止。而对于CyclicBarrier来说,重点是那N个线程,他们之间任何一个没有完成,所有的线程都必须等待。
for example:

public class Test {
    public static void main(String[] args) {
        int N = 4;
        CyclicBarrier barrier  = new CyclicBarrier(N,new Runnable() {
            @Override
            public void run() {
                System.out.println("当前线程"+Thread.currentThread().getName());   
            }
        });

        for(int i=0;inew Writer(barrier).start();
    }
    static class Writer extends Thread{
        private CyclicBarrier cyclicBarrier;
        public Writer(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            System.out.println("线程"+Thread.currentThread().getName()+"正在写入数据...");
            try {
                Thread.sleep(5000);      //以睡眠来模拟写入数据操作
                System.out.println("线程"+Thread.currentThread().getName()+"写入数据完毕,等待其他线程写入完毕");
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }catch(BrokenBarrierException e){
                e.printStackTrace();
            }
            System.out.println("所有线程写入完毕,继续处理其他任务...");
        }
    }
}

参考自:http://www.cnblogs.com/dolphin0520/p/3920397.html

你可能感兴趣的:(多线程并发,多线程)