package ThreadPools_5;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* This is the implementation of {@link LockObjects_4.Worker} with threadPool
* <br><br>
* Codes with minor comments are from
* <a href="http://www.caveofprogramming.com/youtube/">
* <em>http://www.caveofprogramming.com/youtube/</em>
* </a>
* <br>
* also freely available at
* <a href="https://www.udemy.com/java-multithreading/?couponCode=FREE">
* <em>https://www.udemy.com/java-multithreading/?couponCode=FREE</em>
* </a>
*
* @author Z.B. Celik <[email protected]>
*/
class Worker implements Runnable {
private Random random = new Random();
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public List<Integer> list1 = new ArrayList<Integer>();
public List<Integer> list2 = new ArrayList<Integer>();
public void run() {
process();
}
public void process() {
for (int i = 0; i < 1000; i++) {
stageOne();
stageTwo();
}
}
public void stageOne() {
synchronized (lock1) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
//do your work here
e.printStackTrace();
}
list1.add(random.nextInt(100));
}
}
public void stageTwo() {
synchronized (lock2) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
//do your work here
e.printStackTrace();
}
list2.add(random.nextInt(100));
}
}
}
public class WorkerThreadPool {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);//two threads, try setting by 1 to observe time
System.out.println("Starting ...");
long start = System.currentTimeMillis();
Worker worker = new Worker();
for (int i = 0; i < 2; i++) {//worker.run is called 2 (threads started) times by two threads
executor.submit(worker);
}
executor.shutdown(); //prevents new tasks from being accepted by the ExecutorService
try {
executor.awaitTermination(1, TimeUnit.DAYS);
// How long should I wait for termination If I do not know exactly when threads are done with the tasks ?
// Source:http://stackoverflow.com/questions/1250643/how-to-wait-for-all-threads-to-finish-using-executorservice
// For a perpetually running batch kind of thing u need to submit jobs and wait for them to
// finish before jumping ahead.
// In Such a case a latch or a barrier makes more sense than a shutdown (see CountDownLatch_6.App).
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
long end = System.currentTimeMillis();
System.out.println("Time taken: " + (end - start));
System.out.println("List1: " + worker.list1.size() + "; List2: " + worker.list2.size());
}
}
上述代码执行后控制台打印
Starting ...
Time taken: 2183
List1: 2000; List2: 2000
-
shutdown方法:平滑的关闭ExecutorService,当此方法被调用时,ExecutorService停止接收新的任务并且等待已经提交的任务(包含提交正在执行和提交未执行)执行完成。当所有提交任务执行完毕,线程池即被关闭。
-
awaitTermination方法:接收人timeout和TimeUnit两个参数,用于设定超时时间及单位。当等待超过设定时间时,会监测ExecutorService是否已经关闭,若关闭则返回true,否则返回false。一般情况下会和shutdown方法组合使用。
3.shutdownNow方法的作用是向所有执行中的线程发出interrupted以中止线程的运行。这时,各个线程会抛出 InterruptedException异常(前提是
线程中运行了sleep等会抛出异常的方法)
在上述代码中 shutdown方法的意思是等待当前正在执行的线程执行完毕 并且停止接受新的线程执行,如果新开线程的话会抛出RejectedExecutionException异常
awaitTermination的第一个参数是时间,第二个参数是时间单位,在这个地方监视线程是否都执行完毕,如果执行完毕后会执行后面的代码
一般情况下awaitTermination和shutdown配合使用,在上述代码中如果注释掉shutdown方法则awaitTermination不会监视到线程池关闭的信息 所以在这个地方代码会堵塞,
如果注释掉awaitTermination方法 则后面的代码不会得到线程执行过的结果
控制台结果
Starting ...
Time taken: 2
List1: 0; List2: 0
参考资料 点这里