Java多线程(二)线程的并发工具类

·Fork-Join(暂时省略):

  体现了分而治之的思想,就是在必要的情况下,将一个大任务进行拆分(fork)成若干个小人物,再将一个个的小任务的运算结果进行join汇总

 

常用的并发工具类:

  ·CountDownLatch:

    作用:使一个线程等待其他的线程工作完成以后再执行,可以看成加强版join

    初始化的时候必须要带一个count参数,每执行完一个线程count--,当count=0时

    那些有latch.await()方法的线程才会继续执行

package thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

//有五个初始化的线程,有六个扣除点
//扣除完毕以后,主线程和业务线程才能继续自己的工作
public class UseCountDownLatch {

static CountDownLatch latch = new CountDownLatch(6);

//初始化线程
private static class InitThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getId()+
"ready init...");
//表示初始化线程完成工作了
latch.countDown();
for (int i = 0; i < 2; i++) {
System.out.println(Thread.currentThread().getId()+
"....working");
}
}
}

//业务线程,要等待初始化线程结束
private static class BusThread implements Runnable{
@Override
public void run() {
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 3; i++) {
System.out.println("BusThread"+Thread.currentThread().getId()+
"doing business");
}
}
}

public static void main(String[] args) throws InterruptedException {
//单独的初始化线程,
new Thread(new Runnable() {
@Override
public void run() {
try {
TimeUnit.MILLISECONDS.sleep(1);
System.out.println(Thread.currentThread().getId()+
"ready step1");
latch.countDown();//每完成一次初始化操作
TimeUnit.MILLISECONDS.sleep(1);
System.out.println(Thread.currentThread().getId()+
"ready step2");
TimeUnit.MILLISECONDS.sleep(1);
System.out.println(Thread.currentThread().getId()+
"ready step3");
latch.countDown();
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();

new Thread(new BusThread()).start();
for (int i = 0; i < 3; i++) {
new Thread(new InitThread()).start();
}
//所有有await方法的线程都在这里阻塞
latch.await();
System.out.println("main now work");
}
}


·CyclicBarrier:让一组线程到达某个屏障,然后被阻塞,一直到最后这一组内的最后一个线程到达屏障时,屏障开放。
  构造方法也必须传parties参数,和一个Runnable barrierAction参数,
  当屏障开放时,BarrierAction定义的任务会被执行。(这个是自己让自己执行)
  (latch是别人让你执行)



package thread;

import java.util.ConcurrentModificationException;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

public class UseCyclicBarrier {

private static CyclicBarrier barrier = new CyclicBarrier(5, new CollectThread());

private static ConcurrentHashMap<String,Long> resultMap
= new ConcurrentHashMap<>();

public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new SubThread());
thread.start();
}
}

//负责屏障开放以后的工作
private static class CollectThread implements Runnable{
@Override
public void run() {
StringBuilder result = new StringBuilder();
for(Map.Entry<String, Long> workRes : resultMap.entrySet()){
result.append(workRes.getValue()+"**");
}
System.out.println("the result"+result);
System.out.println("do other business");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

//具体的工作线程
private static class SubThread implements Runnable{
@Override
public void run() {
//id视为线程执行的结果
long id = Thread.currentThread().getId();
resultMap.put(Thread.currentThread().getId()+" ",id);
Random r = new Random();
try {
//随机决定工作线程是否睡眠
if (r.nextBoolean()){
Thread.sleep(2000+id);
System.out.println("Thread"+id+"doing sth");
}
//到这里必须等待,
// 等待所有工作线程都到达这个位置以后才能向下走
barrier.await();
Thread.sleep(1000+id);
System.out.println("Thread"+id+"doing business");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}

}
}
}

·Semaphore:
  控制同时访问某个特定资源的线程数量,用在流量控制上面(在多线程获取数据库连接上)
  构造方法参数有int permits,代表同时又多少个线程许可用
  方法tryAcuire、avaliablePermits

 

 


·Exchange:
  线程在执行到exchange.exchange()方法的时候会阻塞,当要交换的数据全都处理好了进行交换
  只能用在两个线程上面,所以使用受限

 

 


·Callable、Future、FutureTask<>
  

 

   get()方法可以获得线程执行结果,是一个阻塞方法,可设置超时时间

  isDone()结束,不论是正常还是异常结束,或者自己取消,返回True

  isCancelled() 任务在完成前被取消,返回True

  cancel()尝试中止任务

    1 任务还没开始,返回false

    2 任务已经启动,cancel(true) 中断正在运行的任务,中断成功返回true

            cancel(false) 不回去中断已经有女性的任务

    3 任务已经结束,返回false


package thread;

import java.sql.Time;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

public class UseFuture {

private static class UseCallable implements Callable<Integer>{
private int sum;

@Override
public Integer call() throws InterruptedException {
System.out.println("开始计算");
Thread.sleep(1000);
for (int i = 0; i < 1000; i++) {
sum = sum+i;
}
System.out.println("计算完成");
return sum;
}
}

public static void main(String[] args) throws InterruptedException, ExecutionException {
UseCallable useCallable = new UseCallable();
FutureTask<Integer> task = new FutureTask<>(useCallable);
new Thread(task).start();
Random r = new Random();
TimeUnit.SECONDS.sleep(2);
if (r.nextBoolean()){
System.out.println("获取值"+task.get());
}else {
System.out.println("中断线程");
task.cancel(true);
}
}

}







posted @ 2020-04-29 23:18  莫西123  阅读(237)  评论(0)    收藏  举报