论坛首页 Java企业应用论坛

说一说java的concurrent包-系列文章

浏览 20694 次
精华帖 (6) :: 良好帖 (5) :: 新手帖 (13) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-03-01  
研究了CountDownLatch源码,发现CAS的经典实用,靠谱的文章,靠谱的理论。
0 请登录后投票
   发表时间:2012-03-02  
zouruixin 写道
还得请教一下。。
如果单纯地计算数组的话,为啥不直接采用如下方式。。。
Long sum = 0l;
    for(int i=0;i<numbers.length;i++){
    sum += numbers[i];
    }
   
    System.out.println(sum);


因为测了一下,你的例子速度比直接循环算的要慢。。
请教请教。。。


这只是一个例子,呵呵。为了说明多线程运行而已。你只要关注如何初始化线程池,将任务加入到线程池就好了。呵呵
0 请登录后投票
   发表时间:2012-03-02  
youjianbo_han_87 写道
zouruixin 写道
还得请教一下。。
如果单纯地计算数组的话,为啥不直接采用如下方式。。。
Long sum = 0l;
    for(int i=0;i<numbers.length;i++){
    sum += numbers[i];
    }
   
    System.out.println(sum);


因为测了一下,你的例子速度比直接循环算的要慢。。
请教请教。。。


这只是一个例子,呵呵。为了说明多线程运行而已。你只要关注如何初始化线程池,将任务加入到线程池就好了。呵呵



多谢了,简化了一下这个例子可能看起来更容易一些。
public class TestExecutors {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//线程池
		ExecutorService exe = Executors.newFixedThreadPool(1);
		//回调
		MyCallable my1 = new MyCallable(1);
		MyCallable my2 = new MyCallable(2);
		//线程
		FutureTask<Integer> task1 = new FutureTask<Integer>(my1);
		FutureTask<Integer> task2 = new FutureTask<Integer>(my2);
		//执行线程
		exe.submit(task1);
		exe.submit(task2);
		
		try {
			System.out.println(task1.get());
			System.out.println(task2.get());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		
	}

}


class MyCallable implements Callable<Integer>{

	private Integer i ;
	
	MyCallable(Integer i){
		this.i=i;
	}
	
	public Integer call() throws Exception {
		
		return i;
	}
	
	
}
0 请登录后投票
   发表时间:2012-03-02   最后修改:2012-03-02
zouruixin 写道
多线程新手请教一下楼主,最后一个例子里,根据cpu拆分起到啥作用?后面的程序有利用cup个数来操作的吗

首先你要区别,你往线程池里面提交任务,并不会马上执行,线程池会判断当前是否有空闲线程,线程池处理速度(也就是多线程切换频率),是和你线程池里面线程数量成正比的。比如你往线程池里面提交了5个task,而你线程池初始化1个线程,那这个多线程其实和顺序执行效率上没有多大差别。你可以测试下。

根据cpu拆分纯粹是一个简单的评估设置线程个数的算法(想法),保证其他程序也能分到cpu,否则,跑多线程时你看看你的cpu,是不是经常90%多...


你看下api-doc上
public static ExecutorService newFixedThreadPool(int nThreads)创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。
0 请登录后投票
   发表时间:2012-03-02  
youjianbo_han_87 写道
zouruixin 写道
多线程新手请教一下楼主,最后一个例子里,根据cpu拆分起到啥作用?后面的程序有利用cup个数来操作的吗

首先你要区别,你往线程池里面提交任务,并不会马上执行,线程池会判断当前是否有空闲线程,线程池处理速度(也就是多线程切换频率),是和你线程池里面线程数量成正比的。比如你往线程池里面提交了5个task,而你线程池初始化1个线程,那这个多线程其实和顺序执行效率上没有多大差别。你可以测试下。

根据cpu拆分纯粹是一个简单的评估设置线程个数的算法(想法),保证其他程序也能分到cpu,否则,跑多线程时你看看你的cpu,是不是经常90%多...


你看下api-doc上
public static ExecutorService newFixedThreadPool(int nThreads)创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。

多谢楼主分享,这个文对我帮助挺大的
0 请登录后投票
   发表时间:2012-03-02  
terry21 写道
楼主几年工作经验?

这个,重要么?
很惭愧的说,我毕业5年了-_-

如果文章写的不好,请多多指点:)谢谢
0 请登录后投票
   发表时间:2012-03-14  
说一说java的concurrent包8–用在一个lock上的多个Condition
http://www.hetaoblog.com/java-concurrent-lock-condition/

concurrent系列的前一篇说到说一说java的concurrent包7–thread和runnable,现在继续,今天介绍下Condtion这个接口,可以用在一个lock上的多个不同的情况;

在jdk的线程同步代码中,无论的synchronized关键字,或者是lock上的await/signal等,都只能在一个锁上做同步通知;
假设有3个线程,要对一个资源做同步,一般只能有一个锁来做同步通知操作,那么通知的时候无法做到精确的通知3个线程中的某一个的;
因为你调用了wait()/notify()的时候,具体的调度是jvm决定的;

但是有的时候的确需要需要对一个锁做多种不同情况的精确通知, 比如一个缓存,满了和空了是两种不同的情况,可以分别通知取数据的线程和放数据的线程;

Condition的基本使用如下:
* Condition是个接口,基本的方法就是await()和signal()方法;
* Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
* 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以
* 和Object.wait()方法一样,每次调用Condition的await()方法的时候,当前线程就自动释放了对当前锁的拥有权

当然,Condition其实是个接口,上面说的这几点,在实现Condition的时候可以自由控制一点;但是jdk的javadoc说了,如果有啥特别的实现,必须要清楚的说明的;

下一节我会结合具体的代码来介绍下Condition的使用;
0 请登录后投票
   发表时间:2012-03-15  
说一说java的concurrent包9–Condition的代码例子BoundedBuffer
http://www.hetaoblog.com/java-concurrent-condition-boundedbuffer-example/
面说了Condition的基本含义,今天这篇说下Condition的一个代码例子;
javadoc里面对Condition有一个绝佳的例子,BoundedBuffer类,就是一个线程安全的有界限的缓存;非常巧妙的利用了Condition,根据来通知不同的线程做不同的事情;
下面先看下具体代码:

class BoundedBuffer {

   final Lock lock = new ReentrantLock();

   final Condition notFull  = lock.newCondition(); 

   final Condition notEmpty = lock.newCondition(); 



   final Object[] items = new Object[100];

   int putptr, takeptr, count;



   public void put(Object x) throws InterruptedException {

     lock.lock();

     try {

       while (count == items.length) 

         notFull.await();

       items[putptr] = x; 

       if (++putptr == items.length) putptr = 0;

       ++count;

       notEmpty.signal();

     } finally {

       lock.unlock();

     }

   }



   public Object take() throws InterruptedException {

     lock.lock();

     try {

       while (count == 0) 

         notEmpty.await();

       Object x = items[takeptr]; 

       if (++takeptr == items.length) takeptr = 0;

       --count;

       notFull.signal();

       return x;

     } finally {

       lock.unlock();

     }

   } 

 }



代码意思不复杂,一个有界的buffer,里面是个数组,可以往里面放数据和取数据;
由于该buffer被多个线程共享,所以每次放和取操作的时候都用一个lock保护起来;
每次取数据(take)的时候,
a. 如果当前个数是0(用一个count计数), 那么就调用notEmpty.await等待,锁就释放了;
b. 取数据的索引专门有一个,每次向前一步; 如果到头了就从0开始循环使用
c.如果有数据,那就取一个数据,将count减1,同时调用notfull.signal(),

每次放数据(put)的时候
a.如果count和length相等,也就是满了,那就调用notFull.await等待,释放了锁; 等待有一些take()调用完成之后才会进入
b. 放数据也有一个索引putptr, 放入数据; 如果到头了也从0开始循环使用
c. 调用notempty.signal(); 如果有线程在take()的时候await住了,那么就会被通知到,可以继续进行操作
0 请登录后投票
   发表时间:2012-03-15  
说一说java的concurrent包10–Condition和BoundedBuffer的测试代码
http://www.hetaoblog.com/java-condition-boundedbuffer-demo/

前面一篇说了Condition和BoundedBuffer的基本代码,下面写一个简单的程序测试下这个BoundedBuffer;

这段程序的目的是测试先put()后take()的操作,
1. 我将BoundedBuffer的大小设置成5,同时在每次进入notFull和notEmpty的await()的时候打印一下表示当前线程正在等待;
2. 先开启10个线程做put()操作,预计有5个线程可以完成,另外5个会进入等待
3. 主线程sleep10秒中,然后启动10个线程做take()操作;

这个时候,首先第一个take()必然成功完成,在这之前等待的5个put()线程都不会被唤醒, 接下来的事情就不好说了;
剩下的5个put()线程和9个take()线程中的任何一个都可能会被jvm调度;
比如可能出现
a. 开始take()的时候,有5个连续的take()线程完成操作; 然后又进入put()和take()交替的情况
b. 第一个take()之后,立刻会有一个put()线程被notFull().signal()唤醒; 然后继续有take()和put()交替的情况;

其中take()线程也可能进入notEmpty.await()操作;
但是任何时候,未完成的take()线程始终>=未完成的put()线程, 这个也是很自然的;



package com.hetaoblog.concurrent.test;



import java.util.Date;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;



import org.junit.Test;



public class BoundedBufferTest {

	

	

	

	@Test

	public void testPutTake()

	{

		

		final BoundedBuffer bb = new BoundedBuffer();

		

		

		int count = 10;

		final CountDownLatch c = new CountDownLatch(count * 2);

		

		

		System.out.println(new Date() + " now try to call put for " + count );

		

		for(int i = 0; i < count ; ++i)

		{

			final int index = i;

			try {

				Thread t = new Thread(new Runnable() {

					

					@Override

					public void run() {

						

						try {

							bb.put(index);

							System.out.println(new Date() + "  put finished:  " + index);

						} catch (InterruptedException e) {

							

							e.printStackTrace();

						}

						

						c.countDown();

					}

				});



				t.start();

				

				

			} catch (Exception e) {

				

				e.printStackTrace();

			}

		}

		

		try {

			System.out.println(new Date() + " main thread is going to sleep for 10 seconds");

			Thread.sleep(10 * 1000);

		} catch (InterruptedException e1) {

			

			e1.printStackTrace();

		}

		

		System.out.println(new Date() + " now try to take for count: " + count);

		

		

		for(int i =0; i < count; ++i)

		{

			

			Thread t= new Thread(new Runnable() {

				

				@Override

				public void run() {

					

					try {

						

						

						Object o = bb.take();

						

						System.out.println(new Date() + " take get: " + o);

					} catch (InterruptedException e) {

						

						e.printStackTrace();

					}

					

					

					

					

					

					

					c.countDown();

					

				}

			});

			

			t.start();

		}

		

		try {

			

			System.out.println(new Date() + ": main thread is to wait for all threads");

			c.await();

			

			

		} catch (InterruptedException e) {

			

			e.printStackTrace();

		}

		

		System.out.println(new Date() + " all threads finished");

		

	}



}

class BoundedBuffer {

	   final Lock lock = new ReentrantLock();

	   final Condition notFull  = lock.newCondition(); 

	   final Condition notEmpty = lock.newCondition(); 



	   final Object[] items = new Object[5];

	   int putptr, takeptr, count;



	   public void put(Object x) throws InterruptedException {

	     lock.lock();

	     try {

	       while (count == items.length) 

	       {

	    	   System.out.println(new Date() + " put  is to wait....");

	         notFull.await();

	       }

	       items[putptr] = x; 

	       if (++putptr == items.length) putptr = 0;

	       ++count;

	       notEmpty.signal();

	     } finally {

	       lock.unlock();

	     }

	   }



	   public Object take() throws InterruptedException {

	     lock.lock();

	     try {

	       while (count == 0)

	       {

	    	   System.out.println(new Date() + " take is going to wait..");

	         notEmpty.await();

	       }

	       Object x = items[takeptr]; 

	       if (++takeptr == items.length) takeptr = 0;

	       --count;

	       notFull.signal();

	       return x;

	     } finally {

	       lock.unlock();

	     }

	   } 

	 }






下面是这段程序在我机器上的运行结果:

这是其中一个执行结果,正好对应前面说的情况a, 5个take()先完成;这里出现了take()线程调用notEmpty.await()的情况
Thu Mar 15 21:15:13 CST 2012 now try to call put for 10
Thu Mar 15 21:15:13 CST 2012 put finished: 0
Thu Mar 15 21:15:13 CST 2012 put finished: 2
Thu Mar 15 21:15:13 CST 2012 put finished: 3
Thu Mar 15 21:15:13 CST 2012 put finished: 1
Thu Mar 15 21:15:13 CST 2012 main thread is going to sleep for 10 seconds
Thu Mar 15 21:15:13 CST 2012 put finished: 4
Thu Mar 15 21:15:13 CST 2012 put is to wait....
Thu Mar 15 21:15:13 CST 2012 put is to wait....
Thu Mar 15 21:15:13 CST 2012 put is to wait....
Thu Mar 15 21:15:13 CST 2012 put is to wait....
Thu Mar 15 21:15:13 CST 2012 put is to wait....
Thu Mar 15 21:15:23 CST 2012 now try to take for count: 10
Thu Mar 15 21:15:23 CST 2012 take get: 3
Thu Mar 15 21:15:23 CST 2012 take get: 2
Thu Mar 15 21:15:23 CST 2012 take get: 1
Thu Mar 15 21:15:23 CST 2012 take get: 0
Thu Mar 15 21:15:23 CST 2012 take get: 4
Thu Mar 15 21:15:23 CST 2012 put finished: 5
Thu Mar 15 21:15:23 CST 2012: main thread is to wait for all threads
Thu Mar 15 21:15:23 CST 2012 take is going to wait..
Thu Mar 15 21:15:23 CST 2012 take get: 5
Thu Mar 15 21:15:23 CST 2012 put finished: 6
Thu Mar 15 21:15:23 CST 2012 put finished: 8
Thu Mar 15 21:15:23 CST 2012 put finished: 7
Thu Mar 15 21:15:23 CST 2012 put finished: 9
Thu Mar 15 21:15:23 CST 2012 take get: 6
Thu Mar 15 21:15:23 CST 2012 take get: 7
Thu Mar 15 21:15:23 CST 2012 take get: 8
Thu Mar 15 21:15:23 CST 2012 take get: 9
Thu Mar 15 21:15:23 CST 2012 all threads finished

这是另一个执行结果:
Thu Mar 15 21:02:49 CST 2012 now try to call put for 10
Thu Mar 15 21:02:49 CST 2012 put finished: 3
Thu Mar 15 21:02:49 CST 2012 put finished: 1
Thu Mar 15 21:02:49 CST 2012 put finished: 0
Thu Mar 15 21:02:49 CST 2012 put finished: 2
Thu Mar 15 21:02:49 CST 2012 put finished: 4
Thu Mar 15 21:02:49 CST 2012 put is to wait....
Thu Mar 15 21:02:49 CST 2012 put is to wait....
Thu Mar 15 21:02:49 CST 2012 put is to wait....
Thu Mar 15 21:02:49 CST 2012 main thread is going to sleep for 10 seconds
Thu Mar 15 21:02:49 CST 2012 put is to wait....
Thu Mar 15 21:02:49 CST 2012 put is to wait....
Thu Mar 15 21:02:59 CST 2012 now try to take for count: 10
Thu Mar 15 21:02:59 CST 2012 take get: 1
Thu Mar 15 21:02:59 CST 2012 take get: 0
Thu Mar 15 21:02:59 CST 2012 take get: 3
Thu Mar 15 21:02:59 CST 2012 take get: 4
Thu Mar 15 21:02:59 CST 2012: main thread is to wait for all threads
Thu Mar 15 21:02:59 CST 2012 take is going to wait..
Thu Mar 15 21:02:59 CST 2012 take is going to wait..
Thu Mar 15 21:02:59 CST 2012 put finished: 5
Thu Mar 15 21:02:59 CST 2012 take get: 2
Thu Mar 15 21:02:59 CST 2012 take get: 5
Thu Mar 15 21:02:59 CST 2012 take is going to wait..
Thu Mar 15 21:02:59 CST 2012 take is going to wait..
Thu Mar 15 21:02:59 CST 2012 put finished: 7
Thu Mar 15 21:02:59 CST 2012 put finished: 6
Thu Mar 15 21:02:59 CST 2012 put finished: 8
Thu Mar 15 21:02:59 CST 2012 put finished: 9
Thu Mar 15 21:02:59 CST 2012 take get: 7
Thu Mar 15 21:02:59 CST 2012 take get: 6
Thu Mar 15 21:02:59 CST 2012 take get: 8
Thu Mar 15 21:02:59 CST 2012 take get: 9
Thu Mar 15 21:02:59 CST 2012 all threads finished

执行结果2:
Thu Mar 15 21:14:30 CST 2012 now try to call put for 10
Thu Mar 15 21:14:30 CST 2012 main thread is going to sleep for 10 seconds
Thu Mar 15 21:14:30 CST 2012 put finished: 8
Thu Mar 15 21:14:30 CST 2012 put finished: 6
Thu Mar 15 21:14:30 CST 2012 put finished: 2
Thu Mar 15 21:14:30 CST 2012 put finished: 0
Thu Mar 15 21:14:30 CST 2012 put finished: 4
Thu Mar 15 21:14:30 CST 2012 put is to wait....
Thu Mar 15 21:14:30 CST 2012 put is to wait....
Thu Mar 15 21:14:30 CST 2012 put is to wait....
Thu Mar 15 21:14:30 CST 2012 put is to wait....
Thu Mar 15 21:14:30 CST 2012 put is to wait....
Thu Mar 15 21:14:40 CST 2012 now try to take for count: 10
Thu Mar 15 21:14:40 CST 2012 take get: 8
Thu Mar 15 21:14:40 CST 2012 take get: 6
Thu Mar 15 21:14:40 CST 2012 take get: 4
Thu Mar 15 21:14:40 CST 2012 take get: 2
Thu Mar 15 21:14:40 CST 2012: main thread is to wait for all threads
Thu Mar 15 21:14:40 CST 2012 take get: 0
Thu Mar 15 21:14:40 CST 2012 take is going to wait..
Thu Mar 15 21:14:40 CST 2012 take is going to wait..
Thu Mar 15 21:14:40 CST 2012 take is going to wait..
Thu Mar 15 21:14:40 CST 2012 put finished: 1
Thu Mar 15 21:14:40 CST 2012 put finished: 5
Thu Mar 15 21:14:40 CST 2012 put finished: 3
Thu Mar 15 21:14:40 CST 2012 put finished: 9
Thu Mar 15 21:14:40 CST 2012 take get: 1
Thu Mar 15 21:14:40 CST 2012 put finished: 7
Thu Mar 15 21:14:40 CST 2012 take get: 5
Thu Mar 15 21:14:40 CST 2012 take get: 3
Thu Mar 15 21:14:40 CST 2012 take get: 7
Thu Mar 15 21:14:40 CST 2012 take get: 9
Thu Mar 15 21:14:40 CST 2012 all threads finished

在几次不同的执行中,始终可以观察到任何时候,未完成的take()线程数>= 未完成的put()线程; 在未完成的线程数相等的情况下,即使jvm首先调度到了take()线程,也会进入notEmpty.await()释放锁,进入等待
0 请登录后投票
   发表时间:2012-03-16  
说一说java的concurrent包11–Condition和BoundedBuffer的测试代码2
http://www.hetaoblog.com/java-concurrent-condition-boundedbuffer-2/

前面一篇说了一个Condition和BoundedBuffer的测试代码例子,前面测试的是先put()再take()的操作,这篇说一下先take()再put()的操作;
当然,必须先要说明的是,这篇和前面这篇在打印日志的时候其实是有错误的,这个错误在前面一篇并不明显,不会导致明显的问题;
但是同样的原因导致现在这个先take()再put()的操作会出现明显的错误,看上去会显得不可思议;
具体情况留到下一篇详细说明,这里先上测试目的,测试代码和运行结果;
同时说明多线程编程需要非常谨慎,否则极易出错

测试目的:
1. 我将BoundedBuffer的大小设置成5,同时在每次进入notFull和notEmpty的await()的时候打印一下表示当前线程正在等待;
2. 先开启10个线程做take()操作,由于开始BoundedBuffer里面没有东西,所以10个线程全部调用await进入等待
3. 主线程sleep10秒中,然后启动10个线程做put()操作;
在第一个put()完成之后,接下来应该会有部分put()线程和take()线程先后完成;
理论上,
a. 任何一个元素的put()都会发生在take()之前;
b. 如果X表示某个操作成功的次数,在X(put)-X(take)<5的时候,put线程不会进入等待状态


下面是测试代码:



	@Test

	public void testTakePut()

	{



		final BoundedBuffer bb = new BoundedBuffer();

		

		

		int count = 10;

		final CountDownLatch c = new CountDownLatch(count * 2);

		



		System.out.println(new Date() + " first try to call take for count: " + count);

		for(int i =0; i < count; ++i)

		{

			final int index = i;

			Thread t= new Thread(new Runnable() {

				

				@Override

				public void run() {

					

					try {

						

						Thread.currentThread().setName(" TAKE " + index);

						

						

						Object o = bb.take();

						

						System.out.println(new Date() + " " + " take get: " + o );

					} catch (InterruptedException e) {

						

						e.printStackTrace();

					}

					

					

					

					

					

					

					c.countDown();

					

				}

			});

			

			t.start();

		}

		

		try {

			System.out.println(new Date() + " main thread is going to sleep for 10 seconds");

			Thread.sleep(10 * 1000);

		} catch (InterruptedException e1) {

			

			e1.printStackTrace();

		}

		

		System.out.println(new Date() + " now try to call put for " + count );

		

		for(int i = 0; i < count ; ++i)

		{

			final int index = i;

			try {

				Thread t = new Thread(new Runnable() {

					

					@Override

					public void run() {

						

						

						Thread.currentThread().setName(" PUT " + index);

						

						try {

							bb.put(index);

							System.out.println(new Date() + " " + "  put finished:  " + index );

						} catch (InterruptedException e) {

							

							e.printStackTrace();

						}

						

						c.countDown();

					}

				});



				t.start();

				

				

			} catch (Exception e) {

				

				e.printStackTrace();

			}

		}

		

		

		try {

			

			System.out.println(new Date() + ": main thread is to wait for all threads");

			c.await();

			

			

		} catch (InterruptedException e) {

			

			e.printStackTrace();

		}

		

		System.out.println(new Date() + " all threads finished");

	}





class BoundedBuffer {

	   final Lock lock = new ReentrantLock();

	   final Condition notFull  = lock.newCondition(); 

	   final Condition notEmpty = lock.newCondition(); 



	   final Object[] items = new Object[5];

	   int putptr, takeptr, count;



	   public void put(Object x) throws InterruptedException {

	     lock.lock();

	     try {

	       while (count == items.length) 

	       {

	    	   System.out.println(new Date() + " " + Thread.currentThread().getName() + " put  is to wait....: " + System.currentTimeMillis());  

	         notFull.await();

	         

	       }

	       items[putptr] = x; 

	       if (++putptr == items.length) putptr = 0;

	       ++count;

	       

	       notEmpty.signal();

	     } finally {

	       lock.unlock();

	     }

	   }



	   public Object take() throws InterruptedException {

	     lock.lock();

	     try {

	       while (count == 0)

	       {

	    	   System.out.println(new Date() + " " + Thread.currentThread().getName() + " take is going to wait.. " + System.currentTimeMillis());  

	         notEmpty.await();

	         

	       }

	       Object x = items[takeptr]; 

	       if (++takeptr == items.length) takeptr = 0;

	       --count;

	       

	       

	       

	       notFull.signal();

	       return x;

	     } finally {

	       lock.unlock();

	     }

	   } 

	 }



运行结果1:
Fri Mar 16 20:50:10 CST 2012 first try to call take for count: 10
Fri Mar 16 20:50:10 CST 2012 TAKE 0 take is going to wait..
Fri Mar 16 20:50:10 CST 2012 TAKE 1 take is going to wait..
Fri Mar 16 20:50:10 CST 2012 TAKE 2 take is going to wait..
Fri Mar 16 20:50:10 CST 2012 TAKE 3 take is going to wait..
Fri Mar 16 20:50:10 CST 2012 TAKE 5 take is going to wait..
Fri Mar 16 20:50:10 CST 2012 main thread is going to sleep for 10 seconds
Fri Mar 16 20:50:10 CST 2012 TAKE 4 take is going to wait..
Fri Mar 16 20:50:10 CST 2012 TAKE 7 take is going to wait..
Fri Mar 16 20:50:10 CST 2012 TAKE 6 take is going to wait..
Fri Mar 16 20:50:10 CST 2012 TAKE 9 take is going to wait..
Fri Mar 16 20:50:10 CST 2012 TAKE 8 take is going to wait..
Fri Mar 16 20:50:20 CST 2012 now try to call put for 10
Fri Mar 16 20:50:20 CST 2012: main thread is to wait for all threads
Fri Mar 16 20:50:20 CST 2012 PUT 7 put finished: 7
Fri Mar 16 20:50:20 CST 2012 PUT 9 put finished: 9
Fri Mar 16 20:50:20 CST 2012 PUT 8 put finished: 8
Fri Mar 16 20:50:20 CST 2012 PUT 3 put is to wait....
Fri Mar 16 20:50:20 CST 2012 PUT 1 put is to wait...
.
Fri Mar 16 20:50:20 CST 2012 PUT 5 put finished: 5
Fri Mar 16 20:50:20 CST 2012 PUT 4 put is to wait....
Fri Mar 16 20:50:20 CST 2012 TAKE 0 take get: 8
Fri Mar 16 20:50:20 CST 2012 TAKE 2 take get: 9
Fri Mar 16 20:50:20 CST 2012 TAKE 3 take get: 0
Fri Mar 16 20:50:20 CST 2012 TAKE 5 take get: 6
Fri Mar 16 20:50:20 CST 2012 TAKE 4 take get: 5
Fri Mar 16 20:50:20 CST 2012 PUT 2 put finished: 2
Fri Mar 16 20:50:20 CST 2012 PUT 3 put finished: 3
Fri Mar 16 20:50:20 CST 2012 PUT 1 put finished: 1
Fri Mar 16 20:50:20 CST 2012 TAKE 7 take get: 2
Fri Mar 16 20:50:20 CST 2012 TAKE 6 take get: 3
Fri Mar 16 20:50:20 CST 2012 TAKE 9 take get: 1
Fri Mar 16 20:50:20 CST 2012 TAKE 8 take get: 4
Fri Mar 16 20:50:20 CST 2012 PUT 6 put finished: 6
Fri Mar 16 20:50:20 CST 2012 PUT 0 put finished: 0
Fri Mar 16 20:50:20 CST 2012 PUT 4 put finished: 4
Fri Mar 16 20:50:20 CST 2012 TAKE 1 take get: 7
Fri Mar 16 20:50:20 CST 2012 all threads finished

注意到红色部分:
第一个加为红色是因为按照打印结果,put()只完成了3次,就开始有put()进入等待了,而BoundedBuffer的大小是5,理论上应该没有满的!
第二个加为红色是因为元素4竟然先被take,然后再被put!

显然程序有地方出错了!具体原因分析,欢迎关注核桃博客:)
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics