《菜鸟记基础篇11》——多线程

阅读: 评论:0

《菜鸟记基础篇11》——多线程

《菜鸟记基础篇11》——多线程

菜鸟记所有篇章都是个人随手记,可能存在知识点遗漏,请多包涵。
本篇章的菜鸟记 概念居多。

本篇目录

  • 一、多线程理论
  • 二、如何实现多线程
    • 1.Thread类
    • 2.实现Runnable接口
    • 2.1线程同步问题(同步锁)
    • 3.实现Callable接口/线程的生命周期
  • 二、死锁
    • 1.线程阻塞对列 ArrayBlockingQueue
  • 三、并发
    • 1Lock锁
    • 2闭锁:
    • 3线程八锁:
    • 4线程池
    • 5.volatile:关键字/原子变量类
    • 6.线程之间的通讯: Condition
    • 7.读写锁
    • 8.分支合并框架ForkJoinPool

一、多线程理论

多线程定义:
什么叫 进程: 在操作系统中,正在运行的程序 叫 进程;
它会占用操作 系统的 内存, 每个进程都有自己独立的内存空间
互相不干扰,这种现象叫 并行; 一个程序中可以有多个 运行的程序出现 ;

什么叫线程:
线程是 运行在 正在执行的程序程序(进程)中的 子程序流,可以有多个
每一个线程 都占用 进程的内存空间,住过程序终止了 ,那么 线程也就不存在了
线程和线程都是独立运行的 相互 不干扰; 他们都公用一个 进程的内存

多线程? 多个线程 并发执行, 高并发;
多个正在执行的 子程序流

小结:
程序 -----> 进程(运行在操作系统后台的)
|-- 线程(main线程)
|-- 子线程 (所有的子线程想要运行 就必须通过 main线程调用)

如何 实现 线程的 并发执行;

二、如何实现多线程

java中如何 实现多线程?
1.继承 Thread 线程类 线程
2.实现Runable 接口 具有线程的功能, 它本身 不是线程
3.实现Callable接口

1.Thread类

Thread类的构造方法:
new Thread();
new Thread(Runnable r);
new Thread(Runnable r , String name);
new Thread(String name); 线程的名字,如果没有 就默认Thread-0

Thread类的常用方法:
1.currentThread(); 返回当前线程 的对象
2.getId();
3.getName();
setName();
4.getPriority(); 获取线程的优先级
setPriority();
5.isDaemon(); 守护线程 最后执行 ,不确定
jvm GC 就是一个守护 线程
setDaemon(true);
toString();

 7.run(); 线程体 , 一般被重写8.start(); 启动线程的方式

线程的生命周期:
6.join(); 强制加入 : 一般用于 main函数下
9.sleep(long millis);
10.yield(); 让步 测试

//模拟迅雷下载电影
public class Demo2 extends Thread{public void run() {for(int i = 1 ; i <=100;i++) {System.out.println(getName()+"正在下载"+i+"%");if(i == 100 ) {System.out.println("下载已完成");}}}public static void main(String[] args) {// TODO Auto-generated method stubDemo2 t = new Demo2();t.setName("张三");t.start();Demo2  t1 = new Demo2 ();t1.setName("小花");t1.start();for(int i = 1 ; i <= 100 ; i++) {System.out.println("小米正在下载"+i+"%");if(i == 10 ) {System.out.println("下载已完成");}}}}

2.实现Runnable接口

实现Runnable接口
A implements Runnable

Thread t = new Thread(a);
t.start();

2.1线程同步问题(同步锁)

多个线程 共享一个资源

在线程并发情况下 , 多个线程共享 一个资源的时候,
有可能出现 资源竞争问题; 多个线程同时 执行的这部分代码

如何解决 这个资源竞争问题 ?
1.java提供了一个 锁机制 同步锁
synchronized 关键字
Lock 接口
lock(); 上锁
unlock(); 释放锁

lock 锁 和 synchronized区别
1.lock()是方法
synchronized 是关键字
2.lock锁必须 手动释放 (会在第三节并发中讲解)
synchronized 自动释放锁 ,jvm虚拟机 的释放
线程的同步: 线程 和 线程 要相互 影响对方
线程的异步: 线程和线程之间 相互 不影响

java中有两种方式来解决 资源竞争问题:
1.同步代码块儿
synchronized(锁标记(对象)){
//这里 编写 核心 代码 ,一般情况下 不会 将循环写在这里
}

2.同步方法

在普通方法上 添加 synchronized

//模拟 火车站售票:  共有四个窗口同时买票  
public class Ticket implements Runnable{int piao = 200;@Overridepublic void run() {while (piao >1 ) {synchronized (this) {	try{Thread.sleep(100);}catch(InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"共卖出了"+piao+"张票");piao--;}}}public static void main(String[] args) {// TODO Auto-generated method stubTicket t = new Ticket();Thread tr = new Thread(t,"1号窗口");tr.start();Thread tr2 = new Thread(t,"2号窗口");tr2.start();Thread tr3 = new Thread(t,"3号窗口");tr3.start();Thread tr4 = new Thread(t,"4号窗口");tr4.start();}	
}

sleep 方法 和 yield方法的区别:
1.sleep方法会让线程进入阻塞状态
yield方法是让线程直接进入就绪状态
2.sleep方法 需要传入 时间片
yield不需要入参
3.sleep方法异常
yield没有异常

4.sleep: sleep方法执行后 ,这个线程回到了 就绪状态,
他会让线程优先高 优先执行
yield: yield执行后,有可能让 线程优先级较低的先执行

yield一般用于测试环境下;

join方法 会让 线程进入阻塞状态:;
调用者 是 强制加入 ,让正在执行的线程 进入阻塞状态
}

3.实现Callable接口/线程的生命周期

Callable接口 是 类似于 Runnable接口的 ,都是实现多线程的方式
但是Callbable 重写的是 call方法 有返回值, 声明异常
run方法没有返回值 , 不声明异常

在使用Callbable接口启动线程时 ,必须使用FutureTask辅助类
来完成启动功能,我们也可以调用FutrueTask辅助类的
get() 获取方法的范沪指, 使用cancel方法 取消摸个线程的执行;

FutureTask:
new FutrueTask(Callable callbale);

get(); 获取返回值
cancel();取消

线程的声明周期:
1.新建 new Thread();
2.就绪 Runnable .start()
5.—> 阻塞 blocked 调用sleep , join ,当sleep时间节点结束, t1.join()结束, IO结束
3.运行 running
4.死亡 death

// 抢苹果案例用Callab 接口实现
public class MyCallable implements Callable<Object> {int count =10;@Overridepublic Object call() throws Exception {int a = 0;while (count > 0){synchronized (this){String name = Thread.currentThread().getName();if ("小红".equals(name)) {a++;}if (count <= 0 ){System.out.println("苹果抢没了");break;}System.out.println(name+"抢到了"+count+"个苹果");count--;Thread.sleep(1000);}}return a;}
}//测试类
public class MyCallableTest {public static void main(String[] args) throws ExecutionException, InterruptedException {MyCallable m = new MyCallable();//使用callable接口时  要用 FutureTask,1个 FutureTask代表一个线程//辅助类FutureTask futureTask = new FutureTask(m);FutureTask futureTask1 = new FutureTask(m);Thread t = new Thread(futureTask,"小红");Thread t1 = new Thread(futureTask1,"小明");t.start();t1.start();Object o = ();System.out.println("抢到了"+o+"次");}
}

二、死锁

什么是死锁?
多个线程 共享 多个 资源时,各自持有 资源不释放, 会导致死锁现象的出现
如何解决死锁?
要在编程时, 是当前释放 资源,让 程序能后继续向下 运行
线程之间的通讯:
Object:
toString();
clone(); 克隆
hashCode(); 返回hash值
equals(); 比较两个对象是否相等
finalize(); 垃圾回收器的

notify(); 唤醒 单个线程 , 唤醒 等待池中 的 任意线程
notifyAll(); 唤醒 所有线程 唤醒 所有等待池中的线程, 这些线程 一起去抢占cpu使用权, 只能用有一个时
wait(); 等待 调用这个方法的线程 ,会进入到等待池中,等待其他线程 唤醒
线程 和 线程之间 必须相互通讯 , 才能保证程序的 正常运行
线程之间的通信除了Obect还有Condition
Condition 比Object 性能要好 使用前提是必须绑定Lock锁的实例(lock锁会在一下目录讲解)
Condition 的方法于Object 差别不大

//经典场景  生产者与消费者public class MianBaoFang {int num =100;public synchronized void  addBread() {if(num >= 100) {System.out.println("做多了 赶紧卖");try {notify();wait();}catch(Exception e) {e.printStackTrace();}}else {num++;System.out.println("生产了一个面包"+num);}}public synchronized void saleBread() {if(num <= 0) {System.out.println("卖没了,赶紧做");try {notify();wait();}catch(Exception e) {e.printStackTrace();}}else {num--;System.out.println("买了一个面包"+num);}}}
//生产者
public class MkBread extends Thread{MianBaoFang mbf;public void run() {while(true) {mbf.addBread();}}}
//消费者
public class ConsumerBread extends Thread{MianBaoFang mbf;public void run() {while(true) {mbf.saleBread();}}}
//测试类
public class TestMbf {public static void main(String[] args) {// TODO Auto-generated method stubMianBaoFang mbf = new MianBaoFang() ;MkBread producter = new MkBread();producter.mbf = mbf;ConsumerBread consumer = new ConsumerBread();consumer.mbf = mbf;producter.start();consumer.start();}}

1.线程阻塞对列 ArrayBlockingQueue

特点 FIFO : put(); take();
常用构造器: ArrayBlockingQueue(int capacity);
常用方法:
1.clear();
2.add(); 添加
3.contains();
4.offer(); 添加
5.peek(); 检索 列头 , 不删除,如果没有返回null
6.poll(); 检索列头 , 删除 , 队列为空,则返回 null 。
7.remove(Object o);
8.size();
9.toArray();

*** put(E e);
在该队列的尾部插入指定的元素,
如果队列已满,则等待空间变为可用。 那此时 就进入到 等待状态
take();
检索并删除此队列的头,如有必要,等待元素可用

以上两个方法 是特殊方法 , 可以让线程进入 阻塞状态,
阻塞功能是 ArrayBlockingQueue 的;

三、并发

JUC: urrent. 1.5 —> java 提供的 并发包
StringBuffer 线程安全
Vector 线程安全
Hashtable 线程安全
ConcurrentHashMap: 锁分段机制
ConcurrentHashMap 和 Hashtable 的区别?

import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import urrent.ConcurrentHashMap;/*** 同步容器* 采用的时分段锁  初始容量和map一样16* 就代表有16个锁   查询快  16个线程同时访问16个 速度指定比hashtable快* **/
public class MyConcurrentHashMap implements Runnable{static ConcurrentHashMap<Integer,String> map = new ConcurrentHashMap<>();static {map.put(1,"张三");map.put(2,"李四");map.put(3,"王五");map.put(4,"赵六");map.put(5,"田七");}@Overridepublic void run() {Set<Map.Entry<Integer, String>> entries = Set();Iterator<Map.Entry<Integer, String>> iterator = entries.iterator();while (iterator.hasNext()){System.out.());map.put(7,"赵云");}}
}public class MyConcurrentHashMapTest {public static void main(String[] args) {MyConcurrentHashMap map = new MyConcurrentHashMap();Thread t1 = new Thread(map);Thread t2 = new Thread(map);Thread t3 = new Thread(map);t1.start();t2.start();t3.start();}
}

ArrayList: 线程不安全, 多个线程在向ArrayList添加元素时
会出现null值,数据丢失问题
Vector可以解决这个问题,因为他是线程安全的,但是不支持 复合操作(一边输出,一边添加)

List list = Collections.synchronizedList(new Array());
这个方式可以将一个线程不安全的 类转换为 线程安全的类但是不支持 复合操作

以上三个都不是最好的, 所以在ent.CopyOnWriteArrayList
及是线程安全的, 有支持 复合操作

CopyOnWriteArrayList: 保证复合操作, 线程安全
复制并写入 添加, 删除 – 》 性能 慢 , 查询快

1Lock锁

lock锁在1.6 1.7 比 synchronized 性能更好,但是1.8进行优化后看不出来了

  • synchronized 更偏向于jvm虚拟机 更偏向于底层
  • lock采用的时 CAS算法: compare and swap
public class MyLock implements Runnable {int count = 100;//创建lock锁的对象Lock lock = new ReentrantLock();@Overridepublic void run() {while (count > 0){try{lock.lock(); //上锁了String name = Thread.currentThread().getName();if (count <= 0 ){System.out.println("苹果抢没了");break;}System.out.println(name+"抢到了"+count+"个苹果");count--;try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}finally {lock.unlock();  //解锁了}}
}
}public class MyLockTest {public static void main(String[] args) {MyLock myLock = new MyLock();new Thread(myLock,"刘备").start();new Thread(myLock,"张飞").start();}
}

2闭锁:

  1. CountDownLatch(int count); 里面维护了一个变量

    这个变量的个数 必须是 线程的个数
    2.await(); 让当前正在执行的线程进入阻塞状态
    3.countDown(); 每次执行这个方式时 会将count 变量-1
    知道为 0 时, 会释放 正在等待的线程

/*** 闭锁* CountDownLathch(int count) 里面维护了一个* await(); 让当前正在执行的线程进入阻塞状态*  countDown(); 每次执行这个方式时,会将count变量-1*  直到为0时 会释放正在等待的线程*/
public class MyCountDown {public static void main(String[] args) {CountDownLatch latch = new CountDownLatch(5);//闭锁 不用调用join  也能完成主函数的阻塞LatchDemo demo = new LatchDemo(latch);//知道这个程序花费的时间long start = System.currentTimeMillis();for (int i = 0; i < 5 ; i++){new Thread(demo).start();}try {latch.await(); //相当于  join} catch (InterruptedException e) {e.printStackTrace();}long end = System.currentTimeMillis();System.out.println("花费的时间为:"+(end - start));}}
class LatchDemo implements Runnable{//闭锁CountDownLatch latch;public LatchDemo(CountDownLatch latch){this.latch = latch;}@Overridepublic void run() {for (int i = 0 ; i < 50000 ; i++){synchronized (this){if (i % 2 == 0){System.out.println(i);}}}untDown();}
}

3线程八锁:

线程八锁: 只的是 使用同步锁的 八种情况;
1.两个线程 调用了 普通同步方法, 直接输出 One Two
两个线程用的是 一把锁
2.两个线程 调用了 普通的同步方法, 在One中休眠了3s, 结果 等待 3s后 一起输出 One Two
3.三个 方法 ,有两个同步方法,一个非同步方法,
两个同步方法持有的是 一个把锁, 非同步方法没有锁,
4.两个普通的 同步方法, 但是创建了两次对象
在调用 One , Two时 输出的是 ,Two 3s One 那说明是两把锁
5. 一个是静态 同步方法, 一个是 普通同步方式
一个对象 ,调用 One ,Two 结果是 Two 3s One 两把锁 ,
一个是 number对象锁, 另一个是 类型的锁
6. 两个 静态 同步方法 ,调用One Two , 结果为: 3s One Two 说明是一把锁
7. 两个静态 同步方法, 两个对象 ,调用One Two ,
结果为: 3s, One Two 说明 一把锁
8. 一个静态同步方法, 一个普通同步方法,
两个Number对象, 调用One, Two ,
Two , 3s , One 两把锁
重点 :
new 一次就是 一个锁 :
所有static 修饰的内容都是一把锁 Class

public class ThreadEightMonitor {public static void main(String[] args) {Number  number = new Number();Number number1 = new Number();//线程1new Thread(new Runnable() {@Overridepublic void run() {One();}}).start();//线程2new Thread(new Runnable() {@Overridepublic void run() {Two();}}).start();/*//线程3new Thread(new Runnable() {@Overridepublic void run() {Three();}}).start();*/}
}
class Number{// 静态 同步方法  锁对象是反射对象  classpublic static synchronized void getOne(){try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("One");}public  synchronized  void getTwo(){System.out.println("Two");}public void getThree(){System.out.println("three");}
}

4线程池

我们在使用线程是 ,我们会频繁的创建 和 销毁线程
是很耗时 和 消耗 性能的; java为了 优化线程的创建和 销毁
体用了一个 叫线程池的 工具

线程池 中维护了 一个 线程队列:
原理 FIFO ,先进先出 ,一定是从第一个位置拿线程
输出结果,不能保证

ExecutorService接口:
常用方法: 给线程池中的线程分配任务
submit(Callable callable);
submit(Ruuable runnable);

shutDown(); 关闭线程池

public class MyExecutors {public static void main(String[] args) {Haha haha = new Haha();//使用线程池ExecutorService Service = wFixedThreadPool(5);for (int i = 0 ; i < 5 ; i++){//给线程池中线程  分配任务Service.submit(haha);}//  线程池  使用后要关闭Service.shutdown();}
}
class  Haha implements Runnable{
Lock lock = new ReentrantLock();@Overridepublic void run() {for (int i = 0 ; i < 100 ; i++){try {lock.lock();if (i % 2 == 0){System.out.println(Thread.currentThread().getName()+" "+i);}} finally {lock.unlock();}}}
}

5.volatile:关键字/原子变量类

.volatile:关键字

*** Volatile 内存可见性问题:*  1、每个线程在操作内存变量时 都会将内存中的拷贝到自己的线程*  缓存中  并且进行一系列的操作  但是  两个线程在操作 共享数据时 内存不可见*  所以导致了,两个线程读取数据不一致* 2、(案例)一共有两个线程 (栈帧) flage的值存储在主存中,主线程运行要比子线程快* 主线程中 while = true(性能特别快  它没有机会重新从主存中读取数据)   一直没有读主存中重新取flage 的值  所以一直没执行* 子线程 将flage的值 改为true  并写入到主存中** 3、解决办法:将内存变为可见就行* 1.上锁 Synchronized(同步锁)  性能慢* 所以java提供了一个关键字  Volatile** 性能速度对比* 不加关键字 > Volatile >synchronized** 注意:* Volatile : 保证了内存的可见性 但是不具备“互斥性”,也不具备“原子性”* 两个线程  如果都有改主存变量的值  不要用* 只可用于 一个 读  一个写** 如何解决volatile 不互斥的功能* 采用cas算法 : Compare and swqp  比较并且交换* 是计算机底层处于硬件保证数据安全性的策略* 原始值:A  3  // ++操作* 预期值:B* 更新值:V* 如果  A == B  就把 B = V;最终还是原始值和更新值比较,如果大于赋值,* 如果 == 就说明  读取的数据不对  就重新从主存中读取,** 原子变量的类:AtomocInteger 既有volatile和CAS算法***/
public class Volatile {public static void main(String[] args) {Volatile1 test = new Volatile1();new Thread(test).start();while (true) {//synchronized (test) {  //用volatile 不用synchronizedif (test.isFlage()) {System.out.println("==========");break;}//  }}}
}
class Volatile1 implements Runnable{
private volatile boolean flage = false; //用Volatile关键字  所有的线程都在主存中操作变量public boolean isFlage() {return flage;}public void setFlage(boolean flage) {this.flage = flage;}@Overridepublic void run() {flage = true;System.out.println("flage的值为:"+isFlage());}public boolean isFlag(){return flage;}
}

原理变量类:
urrent.atomic.*

AtomicInteger: 维护了一个 volatile 关键字修改的 int 变量常用方法: get();incrementAndGet();   ++igetAndIncrement(); 	 i++  getAndDecrement();   i--decrementAndGet();   --i;
import urrent.atomic.AtomicInteger;public class MyAtomicInteger implements Runnable{AtomicInteger count = new AtomicInteger(20);@Overridepublic void run() {() > 0){if (() <= 0){System.out.println("苹果抢没了");break;}System.out.println(Thread.currentThread().getName()+"小朋友抢到了第"&#AndDecrement()+"个苹果");Thread.yield();}}
}public class MyAtomicIntegerTest {public static void main(String[] args) {MyAtomicInteger m = new MyAtomicInteger();Thread t1 = new Thread(m,"小明");Thread t2 = new Thread(m,"小红");t1.start();t2.start();}
}

6.线程之间的通讯: Condition

1.Object :
notify();
notifyAll();
wait();

2.Condition : 使用条件 必须绑定一个 Lock锁的实例

Lock lock = new ReetrantLock();

     wCondition(); 线程之间的通讯

Object类 的方法 和 Condition 方法对比:
Object 类 wait方法 和 await(); 功能一致
notify方法 和 signal();
notifyAll(); 和 signalAll();

注意Condition在使用时 必须 持有 Lock锁的实例
就是不能unlock();

//同样以生产者和消费者的场景为例
public class MyCondition {Random r = new Random();int count = 0; // 总数Lock lock = new ReentrantLock();Condition condition = wCondition();public void make(){try {if (count == 0) {lock.lock();count = r.nextInt(20) + 1;System.out.println("厨师生产了" + count + "个面包");}condition.signalAll();try {condition.await();} catch (InterruptedException e) {e.printStackTrace();}}finally {lock.unlock();}}public void sale(){try {while(count>0){lock.lock();int a = r.nextInt(count)+1;System. out.println("     售货员卖了"+ a + "个面包");count-=a;}condition.signalAll();try {condition.await();} catch (InterruptedException e) {e.printStackTrace();}} finally {lock.unlock();}}
}public class MyConditionTest {public static void main(String[] args) {MyCondition condition = new MyCondition();Cooker cooker = new Cooker(condition);Saler saler = new Saler(condition);Thread t1 = new Thread(cooker);Thread t2 = new Thread(saler);t1.start();t2.start();}
}

7.读写锁

ReentrantReadWriteLock.
调用. ReadLock().lock();
ReentrantReadWriteLock.WriteLock();
调用. WriteLock().lock();
unlock();
unlock();

/*** 读写锁,两个线程对当前的变量进行操作* 一个线程读  一个线程写*/
public class TestReadWriteLock {public static void main(String[] args) {Number1 number = new Number1();// 写for (int i = 0 ; i < 2 ; i++){new Thread(new Runnable() {@Overridepublic void run() {number.setNumer((int)(Math.random()*10));}},"Writer: ").start();}for (int i = 0 ; i < 10; i++ ){// 读new Thread(new Runnable() {@Overridepublic void run() {Numer();}},"Reader: " ).start();}}
}
class Number1{private int numer;ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public void getNumer() {try{adLock().lock();System.out.println(Thread.currentThread().getName()+" "+numer);}finally {adLock().unlock();}}public void setNumer(int numer) {try {lock.writeLock().lock();this.numer = numer;System.out.println(Thread.currentThread().getName() + " " + numer);}finally {lock.writeLock().unlock();}}
}

8.分支合并框架ForkJoinPool

ForkJoinPool : jdk1.8提供的 分支合并框架
机制 “工作窃取” 机制

分支合并框架是 jdk 1.7提供的,只不过是在 jdk1.8才被使用
原理是 将大任务拆分成若干小份,进行递归执行,从而达到
提高解决问题的效率;
ForkJoinPool 是用来执行 整体任务

Object obj = invoke(任务类);

我们在拆分时需要使用 RecursiveTask(带返回值) , RecursiveAction(不带返回值)
帮我们做递归拆分,

RecursiveTask类中的方法:
fork(); 拆分
join(); 合并

/*** 分支合并功能框架 ForkJoinPool jdk1.7提供 只不过在jdk1.8才被使用  在高并发情况下使用比较多* 采用工作“窃取机制” (以计算为例 假设cpu为四核,每一个内核都在处理4个任务,* 第一个内核在处理第一任务完毕之后 第二个任务出现问题,卡出不在执行,第二和第三个内核全部执行完毕* 第四个内核在处理第一任务时就出现卡顿,此时第二内核为空闲状态,第二个内核开始偷第一个内核的第三个任务,* 第三个任务处理完毕开始偷第四个。第三个内核也为空闲状态,开始偷第四个内核的第二个任务,在执行第二个任务时* 第四个内核不在卡顿,开始自己执行)** 原理是将大任务分成若干小份,进行递归执行,从而达到提高解决问题的效率* ForkJoinPool 是用来执行整体任务*Object obj - invoke(任务类);* 我们在拆分时需要使用RecursiveTask(带返回值) RecursiveAction(不带返回值)* 帮我们做递归拆分*RecursiveTask类中* fork();拆分* join();合并**/import java.time.Duration;
import java.time.Instant;
import urrent.ForkJoinPool;
import urrent.RecursiveTask;public class FenZhiHenBinKuangJia {public static void main(String[] args) {/* ForkJoinPool pool = new ForkJoinPool();ForkJoinSumCaculator ff = new ForkJoinSumCaculator(1L,50000000000L);Long invoke = pool.invoke(ff);System.out.println("结果为:"+invoke);*/Instant start = w();long sum = 0;for (int i = 0 ; i <1000000000L; i++ ){sum += i;}System.out.println(sum);Instant end = w();System.out.println("耗费时间为:"+ Duration.between(start,end).toMillis());}
}
class ForkJoinSumCaculator extends RecursiveTask<Long>{private long start;private long end;//临界值public static final  Long THUSHOLD =1000000L;public ForkJoinSumCaculator(long start, long end){this.start =d = end;}//执行分支合并的功能位置@Overrideprotected Long compute() {long length = end -start;if (length < end){long sum = 0;for (int i = 0; i < end ; i++){sum += i;}return sum;}else{//拆分 成5千万long middle = (start + end)/2;ForkJoinSumCaculator left = new ForkJoinSumCaculator(start,middle);left.fork(); //拆分ForkJoinSumCaculator right = new ForkJoinSumCaculator(middle+1,end);right.fork(); //拆分//合并return left.join()+right.join();}}
}

本文发布于:2024-02-03 00:36:16,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170689177647503.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:菜鸟   多线程   基础
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23