这里实际是考察线程间的通信,正常情况下,主线程里启动异步线程执行某个方法,理论上主线程和这个异步线程是并行执行,互不干扰,但是现在要求异步线程执行完毕方法之后,才能继续执行主线程,实际是如何阻塞主线程,到底有几种写法呢?废话少说,直接上代码!
首先先给出需要执行的方法(可以自定义):
public class Compute {
public static int fibo(int a) {
if ( a < 2) {
return 1;
}
return fibo(a-1) + fibo(a-2);
}
}
方式一:Thread.sleep()方法,让主线程休眠
代码:
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
//异步执行
new Thread(() -> {
int result = Compute.fibo(7);
System.out.println("异步线程执行结果:"+result);
}).start();
Thread.sleep(10000);
System.out.println("main线程结束。。。");
}
执行结果:
方式二:用join方法阻塞主线程
代码:
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
myThread.join();
System.out.println("main线程结束。。。");
}
private static class MyThread extends Thread{
@Override
public void run(){
int result = Compute.fibo(7);
System.out.println("异步线程执行结果:"+result);
}
}
执行结果:
方式三:wait+synchronized阻塞主线程
代码:
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
Object obj = new Object();
MyThread myThread = new MyThread();
myThread.start();
synchronized (obj){
obj.wait(1000);
}
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static class MyThread extends Thread{
@Override
public void run(){
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
}
}
执行结果:
方式四:wait+notify+synchronized
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
Object obj = new Object();
MyThread myThread = new MyThread(obj);
myThread.start();
synchronized (obj){
obj.wait();
}
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static class MyThread extends Thread{
Object obj;
public MyThread(Object obj){
this.obj = obj;
}
@Override
public void run(){
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
synchronized (obj) {
obj.notify();
}
}
}
执行结果:
方式五:ReentrantLock+Condition
private final static ReentrantLock reentrantLock = new ReentrantLock(true);
private final static Condition condition = reentrantLock.newCondition();
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
Object obj = new Object();
//异步执行
new Thread(() -> {
ThreadWork05.handler(obj);
}).start();
ThreadWork05.mainHandler(start);
}
private static void mainHandler(long start) throws InterruptedException {
try {
reentrantLock.lock();
condition.await();
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}finally {
reentrantLock.unlock();
}
}
private static void handler(Object obj) {
try {
reentrantLock.lock();
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
condition.signal();
}finally {
reentrantLock.unlock();
}
}
执行结果:
方式六:CountDownLatch
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
long start = System.currentTimeMillis();
//异步执行
new Thread(() -> {
handler();
latch.countDown();
}).start();
latch.await();
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static void handler() {
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
}
执行结果:
方式七:LockSupport.park和unpark
public static void main(String[] args) {
long start = System.currentTimeMillis();
Thread mainThread = Thread.currentThread();
//异步执行
Thread t = new Thread(new Runnable() {
@Override
public void run() {
handler(mainThread);
}
});
t.start();
LockSupport.park(mainThread);
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static void handler(Thread mainThread) {
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
LockSupport.unpark(mainThread);
}
执行结果:
方式八:LockSupport.parkNanos 超时时间
public static void main(String[] args) {
long start = System.currentTimeMillis();
Thread mainThread = Thread.currentThread();
//异步执行
Thread t = new Thread(new Runnable() {
@Override
public void run() {
handler();
}
});
t.start();
LockSupport.parkNanos(mainThread, 100L);
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static void handler() {
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
}
执行结果:
方式九:LockSupport.parkUntil 截止到某时间点释放方式
public static void main(String[] args) {
long start = System.currentTimeMillis();
Thread mainThread = Thread.currentThread();
//异步执行
Thread t = new Thread(new Runnable() {
@Override
public void run() {
handler();
}
});
t.start();
LockSupport.parkUntil(mainThread, System.currentTimeMillis()+1000);
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static void handler() {
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
}
执行结果:
方式十:CountDownLatch.await(long t, TimeUtil t)
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
long start = System.currentTimeMillis();
//异步执行
new Thread(() -> {
handler();
}).start();
latch.await(100, TimeUnit.MILLISECONDS);
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static void handler() {
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
}
执行结果:
方式十一:ExecutorService.submit+Future.get()阻塞 线程池
public static void main(String[] args) {
long start = System.currentTimeMillis();
ExecutorService executorService = new ThreadPoolExecutor(2,2,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>());
Future<Integer> future = executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return handler();
}
});
try {
System.out.println("异步线程输出结果:"+future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static int handler() {
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
return result;
}
执行结果:
方式十二:线程池+synchronized 方式,下面要么同时锁住oo,要么同时锁住mainThread,效果一样
public static void main(String[] args) {
Object oo = new Object();
Thread mainThread = Thread.currentThread();
long start = System.currentTimeMillis();
ExecutorService executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
executorService.execute(new Runnable() {
@Override
public void run() {
handler(oo, mainThread);
}
});
executorService.shutdown();
synchronized (mainThread){
try {
mainThread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static int handler(Object oo, Thread mainThread) {
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
synchronized (mainThread){
mainThread.notify();
}
return result;
}
执行结果:
方式十三:FutureTask+异步线程启动+future.get()阻塞
public static void main(String[] args) {
long start = System.currentTimeMillis();
FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return handler();
}
});
//异步启动
new Thread(futureTask).start();
try {
System.out.println("异步线程输出结果:"+futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static int handler() {
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
return result;
}
执行结果:
方式十四:CompletableFuture.supplyAsync() ,分为指定线程池和默认线程池两种
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
//如果不指定线程池默认使用ForkJoinPool.commonPool()
// CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
// return handler();
// });
//也可以指定线程池
ExecutorService executorService = new ThreadPoolExecutor(2,2,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>());
CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
return handler();
}, executorService);
System.out.println("异步输出结果:"+integerCompletableFuture.get());
//如果指定了线程池得关闭
executorService.shutdown();
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static int handler() {
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
return result;
}
执行结果:
方式十五:CompletableFuture.runAsync() ,分为指定线程池和默认线程池两种
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
//如果不指定线程池默认使用ForkJoinPool.commonPool()
CompletableFuture<Void> integerCompletableFuture = CompletableFuture.runAsync(() -> {
handler();
});
//也可以指定线程池
// ExecutorService executorService = new ThreadPoolExecutor(2,2,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>());
// CompletableFuture<Void> integerCompletableFuture = CompletableFuture.runAsync(() -> {
// handler();
// }, executorService);
//runAsync没有返回值,输出为null
System.out.println("异步输出结果:"+integerCompletableFuture.get());
//如果指定了线程池得关闭
// executorService.shutdown();
System.out.println("线程:"+Thread.currentThread().getName()+" 使用时间:"+(System.currentTimeMillis()-start)+"ms");
}
private static int handler() {
int result = Compute.fibo(7);
System.out.println("线程:"+Thread.currentThread().getName()+" 异步计算结果:"+result);
return result;
}
执行结果: