Callable接口的使用
比Runnable接口功能更多
- 有返回值
- 还能抛出异常
package com.unsafe;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
new Thread(new Test()).start();
/* new Thread(new Runnable() {
@Override
public void run() {
System.out.println("123");
}
}).start();*/
FutureTask futureTask = new FutureTask(new MyThread());
new Thread(futureTask).start();
System.out.println(futureTask.get());
}
}
class MyThread implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("call()方法");
return "开启成功";
}
}
class Test implements Runnable {
@Override
public void run() {
System.out.println("原来的开启线程的方法");
}
}
实现Callable接口来开启两个线程,此时会打印几个call()方法?
1个 ,因为会缓存来提高效率
细节:
- 有缓存
- 返回结果可能需要等待,阻塞
CountDownLatch用法
指定当前线程等到其它n个线程执行完后再继续执行
每执行一个线程可手动调用countDown() 让计数器-1,计数器为0时,await方法后面的代码才能继续执行。
- 原来
package com.unsafe;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class CountDownLatchPra {
public static void main(String[] args) throws InterruptedException {
// CountDownLatch countDownLatch = new CountDownLatch(6);
new Thread(()->{
for (int i = 0; i < 6; i++) {
System.out.println(i+" 离开");
// countDownLatch.countDown();
}
}).start();
// countDownLatch.await();
System.out.println("关门");
}
}
- 现在
package com.unsafe;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class CountDownLatchPra {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
new Thread(()->{
for (int i = 0; i < 6; i++) {
System.out.println(i+" 离开");
countDownLatch.countDown();
}
}).start();
countDownLatch.await();
System.out.println("关门");
}
}
countDownLatch.countDown();//数量-1
countDownLatch.await(); //等待计数器归零,然后再向下执行
每次有线程调用countDown,数量-1,计数器变为0时,await()就会被唤醒,继续执行~
CyclicBarrier用法,和countDownLatch相似
package com.unsafe;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierPra {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,new Thread(()->{
System.out.println("到7了");
}));
for (int i = 0; i < 7; i++) {
int temp = i;
new Thread(()->{
System.out.println(temp+"开启");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
有7个线程开启之后会调用new CyclicBarrier构造函数里头实现Runnable接口的方法
计数器不断+1 直到7
Semaphore用法
用来对线程进行像车一样的限流
保证不多于n个线程运行,其余线程等待,直到其中有线程运行结束后自动唤醒部分剩余线程
多个共享的资源互斥使用 控制最大的线程数量
package com.unsafe;
import io.netty.util.internal.ThreadExecutorMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphorePra {
public static void main(String[] args) {
//限流
// 理解为线程停车场,此时停车位为3个 如果车位满了,剩下的线程就等待,直到有空位置为止
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 6; i++) {
new Thread(
()->{
try {
semaphore.acquire();
// 获得 如果有3个线程了就等,直到有空余位置
System.out.println(Thread.currentThread().getName()+"进来了");
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName()+"离开了");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();//释放,空出车位
}
},String.valueOf(i)
).start();
}
}
}