从头认识java-17.2 基本的线程机制(2)-Executors的使用

在前面的章节我们都是直接对Thread进行管理,我们这里解释一下另一个管理Thread的类Executors。

1.例子:

package com.ray.ch17;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {

	public static void main(String[] args) throws InterruptedException {
		long startTime = System.currentTimeMillis();
		ExecutorService executorService = Executors.newCachedThreadPool();
		CountDownLatch countDownLatch = new CountDownLatch(5);
		for (int i = 5; i < 10; i++) {
			DoneMission doneMission = new DoneMission(i, countDownLatch);
			executorService.execute(doneMission);
		}
		executorService.shutdown();
		countDownLatch.await();
		long endTime = System.currentTimeMillis();
		System.out.println();
		System.out.println(endTime - startTime);
	}
}

class DoneMission implements Runnable {
	private final int id = index++;
	private int count = 0;
	private static int index = 0;
	private CountDownLatch countDownLatch;

	public DoneMission(int count, CountDownLatch countDownLatch) {
		this.count = count;
		this.countDownLatch = countDownLatch;
	}

	public String leftMission() {
		return "#" + id + "(" + count + ") ";
	}

	@Override
	public void run() {
		while (count-- > 0) {
			System.out.print(leftMission());
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Thread.yield();
		}
		countDownLatch.countDown();
	}
}

解释:

(1)运行任务的类跟前面的基本一致

(2)使用Executors.newCachedThreadPool()生成线程池,当需要线程驱动的时候,我们可以到里面拿,它生成的线程数是有系统控制的。

2.对线程的数量做出控制

package com.ray.ch17;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {

	public static void main(String[] args) throws InterruptedException {
		long startTime = System.currentTimeMillis();
		ExecutorService executorService = Executors.newFixedThreadPool(5);//控制线程的数量
		CountDownLatch countDownLatch = new CountDownLatch(5);
		for (int i = 5; i < 10; i++) {
			DoneMission doneMission = new DoneMission(i, countDownLatch);
			executorService.execute(doneMission);
		}
		executorService.shutdown();
		countDownLatch.await();
		long endTime = System.currentTimeMillis();
		System.out.println();
		System.out.println(endTime - startTime);
	}
}

class DoneMission implements Runnable {
	private final int id = index++;
	private int count = 0;
	private static int index = 0;
	private CountDownLatch countDownLatch;

	public DoneMission(int count, CountDownLatch countDownLatch) {
		this.count = count;
		this.countDownLatch = countDownLatch;
	}

	public String leftMission() {
		return "#" + id + "(" + count + ") ";
	}

	@Override
	public void run() {
		while (count-- > 0) {
			System.out.print(leftMission());
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Thread.yield();
		}
		countDownLatch.countDown();
	}
}

上面的代码只是替换了一句,就可以控制线程的数量,但是我们一般还是建议使用cache的那个,因为它对线程池做出来优化。特别是对于短的异步任务它具有明显优势。

3.测试不同线程运行的时间:

package com.ray.ch17;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {

	public static void main(String[] args) throws InterruptedException {
		long startTime = System.currentTimeMillis();
		ExecutorService executorService = Executors.newCachedThreadPool();
		CountDownLatch countDownLatch = new CountDownLatch(5);
		for (int i = 5; i < 10; i++) {
			DoneMission doneMission = new DoneMission(i, countDownLatch);
			executorService.execute(doneMission);
		}
		executorService.shutdown();
		countDownLatch.await();
		long endTime = System.currentTimeMillis();
		System.out.println();
		System.out.println("time:"+(endTime - startTime));
	}
}

class DoneMission implements Runnable {
	private final int id = index++;
	private int count = 0;
	private static int index = 0;
	private CountDownLatch countDownLatch;

	public DoneMission(int count, CountDownLatch countDownLatch) {
		this.count = count;
		this.countDownLatch = countDownLatch;
	}

	public String leftMission() {
		return "#" + id + "(" + count + ") ";
	}

	@Override
	public void run() {
		while (count-- > 0) {
			System.out.print(leftMission());
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Thread.yield();
		}
		countDownLatch.countDown();
	}
}

输出:

#0(4) #1(5) #2(6) #3(7) #4(8) #0(3) #1(4) #4(7) #3(6) #2(5) #0(2) #1(3) #3(5) #2(4) #4(6) #0(1) #1(2) #4(5) #3(4) #2(3) #0(0) #1(1) #2(2) #4(4) #3(3) #1(0) #2(1) #3(2) #4(3) #4(2) #3(1) #2(0) #3(0) #4(1) #4(0) 
904

控制为3个线程:

package com.ray.ch17;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {

	public static void main(String[] args) throws InterruptedException {
		long startTime = System.currentTimeMillis();
		ExecutorService executorService = Executors.newFixedThreadPool(3);
		CountDownLatch countDownLatch = new CountDownLatch(5);
		for (int i = 5; i < 10; i++) {
			DoneMission doneMission = new DoneMission(i, countDownLatch);
			executorService.execute(doneMission);
		}
		executorService.shutdown();
		countDownLatch.await();
		long endTime = System.currentTimeMillis();
		System.out.println();
		System.out.println(endTime - startTime);
	}
}

class DoneMission implements Runnable {
	private final int id = index++;
	private int count = 0;
	private static int index = 0;
	private CountDownLatch countDownLatch;

	public DoneMission(int count, CountDownLatch countDownLatch) {
		this.count = count;
		this.countDownLatch = countDownLatch;
	}

	public String leftMission() {
		return "#" + id + "(" + count + ") ";
	}

	@Override
	public void run() {
		while (count-- > 0) {
			System.out.print(leftMission());
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Thread.yield();
		}
		countDownLatch.countDown();
	}
}

输出:

#0(4) #2(6) #1(5) #1(4) #0(3) #2(5) #0(2) #2(4) #1(3) #1(2) #2(3) #0(1) #0(0) #1(1) #2(2) #1(0) #2(1) #3(7) #3(6) #4(8) #2(0) #3(5) #4(7) #3(4) #4(6) #3(3) #4(5) #4(4) #3(2) #4(3) #3(1) #4(2) #3(0) #4(1) #4(0) 
1504

控制为单线程:

package com.ray.ch17;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {

	public static void main(String[] args) throws InterruptedException {
		long startTime = System.currentTimeMillis();
		ExecutorService executorService = Executors.newSingleThreadExecutor();
		CountDownLatch countDownLatch = new CountDownLatch(5);
		for (int i = 5; i < 10; i++) {
			DoneMission doneMission = new DoneMission(i, countDownLatch);
			executorService.execute(doneMission);
		}
		executorService.shutdown();
		countDownLatch.await();
		long endTime = System.currentTimeMillis();
		System.out.println();
		System.out.println(endTime - startTime);
	}
}

class DoneMission implements Runnable {
	private final int id = index++;
	private int count = 0;
	private static int index = 0;
	private CountDownLatch countDownLatch;

	public DoneMission(int count, CountDownLatch countDownLatch) {
		this.count = count;
		this.countDownLatch = countDownLatch;
	}

	public String leftMission() {
		return "#" + id + "(" + count + ") ";
	}

	@Override
	public void run() {
		while (count-- > 0) {
			System.out.print(leftMission());
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Thread.yield();
		}
		countDownLatch.countDown();
	}
}

输出:

#0(4) #0(3) #0(2) #0(1) #0(0) #1(5) #1(4) #1(3) #1(2) #1(1) #1(0) #2(6) #2(5) #2(4) #2(3) #2(2) #2(1) #2(0) #3(7) #3(6) #3(5) #3(4) #3(3) #3(2) #3(1) #3(0) #4(8) #4(7) #4(6) #4(5) #4(4) #4(3) #4(2) #4(1) #4(0) 
3503

单线程说白了就像直接在main方法里面使用for来运行的一样。

4.关于shutdown()(下面的这段话摘自http://my.oschina.net/bairrfhoinn/blog/177639,笔者觉得他解释的已经比较清楚,其实关键是笔者比较懒,不喜欢打字)

为了关闭在 ExecutorService 中的线程,你需要调用 shutdown() 方法。ExecutorService 并不会马上关闭,而是不再接收新的任务,一旦所有的线程结束执行当前任务,ExecutorServie 才会真的关闭。所有在调用 shutdown() 方法之前提交到 ExecutorService 的任务都会执行。 
如果你希望立即关闭 ExecutorService,你可以调用 shutdownNow() 方法。这个方法会尝试马上关闭所有正在执行的任务,并且跳过所有已经提交但是还没有运行的任务。但是对于正在执行的任务,是否能够成功关闭它是无法保证的,有可能他们真的被关闭掉了,也有可能它会一直执行到任务结束。

总结:这一章节主要介绍Executors的使用。

这一章节就到这里,谢谢。

-----------------------------------

目录

时间: 2024-10-06 23:56:29

从头认识java-17.2 基本的线程机制(2)-Executors的使用的相关文章

Java并发编程-如何终止线程

我们知道使用stop().suspend()等方法在终止与恢复线程有弊端,会造成线程不安全,那么问题来了,应该如何正确终止与恢复线程呢?这里可以使用两种方法: 1.使用interrupt()中断方法. 2.使用volatile boolean变量进行控制. 在使用interrupt方法之前,有必要介绍一下中断以及与interrupt相关的方法.中断可以理解为线程的一个标志位属性,表示一个运行中的线程是否被其他线程进行了中断操作.这里提到了其他线程,所以可以认为中断是线程之间进行通信的一种方式,简

Java 理论和实践:线程池和工作队列

使用线程池以获取最佳资源利用率 Java 多线程编程论坛中最常见的一个问题就是各种版本的 "我怎么样才可以创建一个线程池?" 几乎在每个服务器应用里,都会出现关于线程池和工作队列的问题.本文中,Brian Goetz 就线程池原理.基本实现和调优技术.需要避开的一些常见误区等方面进行共享. 为何要用线程池? 有很多服务器应用,比如 Web 服务器,数据库服务器,文件服务器,或者邮件服务器,都会面对处理大量来自一些远程请求的小任务.请求可能会以很多种方式到达服务器,比如通过一种网络协议(

[Java]#从头学Java# Java大整数相加

重操旧业,再温Java,写了个大整数相乘先回顾回顾基本知识.算法.效率什么的都没怎么考虑,就纯粹实现功能而已. 先上代码: 1 package com.tacyeh.common; 2 3 public class MyMath { 4 5 public static String BigNumSum(String... n) { 6 int length = n.length; 7 StringBuilder result = new StringBuilder(); 8 //这里判断其实不需

java 22 - 18 多线程之 线程的状态转换、线程组

线程的状态转换图解:..博客暂时不能上传图片 线程的线程组: 线程组: 把多个线程组合到一起.    它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制. 首先创建一个Runnable的实现类 public class MyRunnable implements Runnable { public void run() { for(int x = 0; x < 10 ; x++){ System.out.println(x); } } } 先看看默认状态下,线程都会保存在哪个线程

Java多线程之 -- 进程和线程

Java多线程之 – 进程和线程 概念 进程 程序的动态执行过程 包括占用的资源(内存.CPU)和线程 线程 线程是程序中最小的执行单位 一个进程有多个线程 线程共享进程的资源 进程和线程的区分 我们可以想象为进程为班级而线程是邦奇中得每一个学生 线程之间的交互 互斥,类似于每一个学生都为了第一名而你争我让,线程也是,都想抢占CPU的资源 同步,当举行运动会的时候,大家都团结一心,彼此共享自己的资源 Thread.Runnable Thread Introduction Thread 是Java

java中volatile不能保证线程安全(实例讲解)

java中volatile不能保证线程安全(实例讲解) 转载  2017-09-04   作者:Think-007    我要评论 下面小编就为大家带来一篇java中volatile不能保证线程安全(实例讲解).小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 今天打了打代码研究了一下java的volatile关键字到底能不能保证线程安全,经过实践,volatile是不能保证线程安全的,它只是保证了数据的可见性,不会再缓存,每个线程都是从主存中读到的数据,而不是从缓存

学习笔记2:java中Thread类与线程的创建

线程 是程序中的执行线程.Java 虚拟机允许应用程序并发地运行多个执行线程. 每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程.每个线程都可以或不可以标记为一个守护程序.当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序. 当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main 方法).Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:

JAVA技术专题综述之线程篇(1)

本文详细介绍JAVA技术专题综述之线程篇 编写具有多线程能力的程序经常会用到的方法有: run(),start(),wait(),notify(),notifyAll(),sleep(),yield(),join() 还有一个重要的关键字:synchronized 本文将对以上内容进行讲解. 一:run()和start() 示例1: public cla ThreadTest extends Thread{public void run(){for(int i=0;i<10;i++){Syste

我对java中任务取消和线程中断的一点儿理解

在JDK中任务就是一个Runnable或Callable对象,线程是一个Thread对象,任务是运行在某个线程中的.我们知道,让线程死亡的方式有2种:正常完成和未捕获的异常.如果想让任务结束,也只有这2种方式. java中虽然提供了抢占式中断Thread.stop(),但这是很不安全的,JDK早已经将其标记成过时的了.在java中如果想取消一个任务,只能使用中断,中断是一种协作机制.也就是说,如果A线程想中断B线程,那么其实是A向B发送了一个中断请求,至于B到底会不会停止执行,取决于B的实现.如

Java中的进程和线程

 Java中的进程与线程 一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程:进程是指处于运行过程中的程序,并且具有一定的独立功能.进程是系统进行资源分配和调度的一个单位.当程序进入内存运行时,即为进程. 进程的三个特点: 1:独立性:进程是系统中独立存在的实体,它可以独立拥有资源,每一个进程都有自己独立的地址空间,没有进程本身的运行,用户进程不可以直接访问