多个线程分别顺序交替打印一种不同字符abcdefg(已实现随便多少个线程打印多少个字符,利用线程池实现多线程)
下面实现多线程顺序打印字符"abcdefg";
实现Runnable接口:
/**
* @author: rhyme
* @date: 2019-08-17 14:39
* @topic: "Runnable"
* @description: "每个线程通过sign表示需要打印的字符数组下标,index表示将要打印的字符数组的下标"
*/
public class PrintRunnable implements Runnable { private final char[] chars;
/**
* 当前线程只能打印的那个字符对应数组的下标
*/
private final int sign;
/**
* 当前将要打印的字符数组下标
*/
private volatile static int index; private final static Class<PrintRunnable> CLASS_LOCK = PrintRunnable.class; public PrintRunnable(String chars, int sign) {
this.chars = chars.toCharArray();
this.sign = sign;
} @Override
public void run() {
try {
while (true) {
// 为了结合线程池shutdownNow方法设置中断interrupt停止线程
/*if (Thread.currentThread().isInterrupted()) {
break;
}*/ synchronized (CLASS_LOCK) {
if (index % chars.length == sign) {
System.out.printf("ThreadName : %s is printing (%c)\n", Thread.currentThread().getName(), chars[sign]);
index++;
CLASS_LOCK.notifyAll();
} CLASS_LOCK.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
System.err.printf("ThreadName : %s InterruptedException\n", Thread.currentThread().getName());
}
}
}
这里实现Runnable接口,两个重要的属性sign和index;
sign表示当前线程打印的那个字符在字符数组中的下标;
index表示移动字符下标打印, index % chars.length(重要,顺序打印的核心实现)的值表示需要打印的字符的下标,当一个字符被打印,index++;
chars表示一个字符数组;
wait()这里有两个作用,一个是为了让当前线程等待不马上循环获取锁影响效率,另一个可以通过设置线程中断interrupt抛异常停止;
notifyAll唤醒所有对应锁wait()的线程;
这里也可以不用wait和notifyAll,那每个线程就不会wait,重复循环获取锁,占用资源影响效率,其次可判断线程是否被设为中断,则break退出循环。
利用线程池启动:
import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.util.concurrent.*; /**
* @author: rhyme
* @date: 2019-08-17 14:37
* @topic: "多个线程打印"
* @description: "多个线程有序打印abcdefg"
*/
public class MultiThreadPrintOrder {
public static void main(String[] args) throws InterruptedException {
final String string = "abcdefg"; ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("order-pool-%d")
.build(); ExecutorService threadPoolExecutor =
new ThreadPoolExecutor(
string.length(),
string.length(),
0L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1),
namedThreadFactory,
new ThreadPoolExecutor.AbortPolicy()); for (int i = 0; i < string.length(); i++) {
threadPoolExecutor.execute(new PrintRunnable(string, i));
} // 3秒后线程池调用shutdownNow设置线程中的interrupt中断标志位
TimeUnit.SECONDS.sleep(3);
System.out.printf("ThreadName: (%s) Preparing call shutdownNow()...\n", Thread.currentThread().getName());
threadPoolExecutor.shutdownNow(); }
}
这里通过guava包中ThreadFactoryBuilder设置线程池中的线程名;
提交string.length()个不同的线程任务(通过下标i打印不同的字符)到线程池中;
3秒后,主线程调用shutdownNow,这里主要是为了将正在运行的线程设置中断标志位,死循环利用中断标志位结束循环,或线程调用了等待方法(如wait)会抛出异常InterruptException未被捕获而停止。
shutdownNow 方法:此方法执行后不得向线程池再提交任务,如果有空闲线程则销毁空闲线程,取消所有位于阻塞队列中的任务,并将其放入 List容器,作为返回值;取消正在执行的线程(实际上仅仅是设置正在执行线程的中断标志位,调用线程的 interrupt 方法来中断线程)。
启动main方法,多个线程按顺序打印"abcdefg",3s后结束,执行结果部分截图如下:

当然也可以通过另一种"等待-唤醒"机制实现,如用一个ReentrantLock对象的的newCondition()方法创建多个Condition对象,再利用Condition对象的await()搭配signal()或signalAll();
也可利用取余运算%判断线程需要打印的字符,不用生成多个 Condition对象,可利用一个Condition对象,而且可以改变,随便多少个线程打印多少个字符。
JAVA线程状态、线程START方法源码、多线程、JAVA线程池、如何停止一个线程
多个线程分别顺序交替打印一种不同字符abcdefg(已实现随便多少个线程打印多少个字符,利用线程池实现多线程)的更多相关文章
- 多线程面试题之【三线程按顺序交替打印ABC的方法】
		
建立三个线程,线程名字分别为:A.B.C,要求三个线程分别打印自己的线程名字,但是要求三个线程同时运行,并且实现交替打印,即按照ABCABCABC的顺序打印.打印10轮,打印完毕控制台输出字符串:&q ...
 - 三个线程ABC,交替打印ABC
		
转载与:https://www.cnblogs.com/x_wukong/p/4009709.html 创建3个线程,让其交替打印ABC . 输出如下: ABCABCABCABC. 方法:使用syn ...
 - 用三个线程按顺序循环打印ABC三个字母
		
有两种方法:semaphore信号量和mutex互斥锁.需要注意的是C++11已经没有semaphore. C++ 并发编程(六):信号量(Semaphore) - 止于至善 - SegmentFau ...
 - 三个线程T1,T2,T3.保证顺序执行的三种方法
		
经常看见面试题:有三个线程T1,T2,T3,有什么方法可以确保它们按顺序执行.今天手写测试了一下,下面贴出目前想到的3种实现方式 说明:这里在线程中我都用到了sleep方法,目的是更容易发现问题.之前 ...
 - C#之使用AutoResetEvent实现线程的顺序执行
		
前几天一朋友问我如何实现线程的顺序执行,说真的,虽然看过CLR这本书,也把线程部分拜读了两遍,但是这个问题出来之后还是没有一个思路.今天在搜索资料的时候无意中再次看到AutoResetEvent这个东 ...
 - Qt 控制线程的顺序执行(使用QWaitCondition,并且线程类的run函数里记得加exec(),使得线程常驻)
		
背景项目中用到多线程,对线程的执行顺序有要求: A.一个线程先收数据 B.一个线程处理数据 C.一个线程再将处理后的数据发送出去 要求三个线程按照ABC的顺序循环执行. 思路子类化多线程方法 重写子类 ...
 - 【Java多线程系列四】控制线程执行顺序
		
假设有线程1/线程2/线程3,线程3必须在线程1/线程2执行完成之后开始执行,有两种方式可实现 Thread类的join方法:使宿主线程阻塞指定时间或者直到寄生线程执行完毕 CountDownLatc ...
 - 实现线程按顺序输出ABC
		
线程按顺序输出ABC 实现描述:建立三个线程A.B.C,分别按照顺序输出十次ABC 首先建立一个方法,按照条件进行输出 class PrintABC{ private int index=0; pub ...
 - Java之CountDownLatch ---控制线程执行顺序
		
一,类介绍 这是java.util.concurrent包里的一个同步辅助类,它有两个主要的常用方法 countDown()方法以及await()方法.在完成一组正在其他线程中执行的操作之前,它允许 ...
 
随机推荐
- svn"重新定位"提示版本库uuid不匹配
			
svn"重新定位"提示版本库 uuid不匹配: 版本库 "https://wolfcome110/svn/andon" 的 uuid是 "d52648 ...
 - 1-3docker commit定制镜像
			
以定制⼀个 Web 服务器为例⼦ 1.commit定制镜像 docker pull nginx:1.17 运行容器 --name:容器名字 -d:后台 -p本地端口:容器内端口 docker ru ...
 - 使用命令行操作vmware esxi -- linux
			
为实现自动化,发现了两种命令行工具,一是开启vmware esxi后用xshell等连接工具去连接esxi后台:二是安装powercli连接.本文将介绍一些常用的命令去操作vmware esxi 本文 ...
 - 一段隐藏文字的css代码,记录下
			
<span style="width:1px; height:1px; color:#fff; outline-width:hidden; overflow:hidden; displ ...
 - Linux系统下的SSH 使用总结
			
对于linux运维工作者而言,使用ssh远程远程服务器是再熟悉不过的了!对于ssh的一些严格设置也关系到服务器的安全维护,今天在此,就本人工作中使用ssh的经验而言,做一些总结记录来下. -bash: ...
 - thinkphp3.2.2公用函数
			
thinkphp3.2.2公用函数函数调用默认路径 home/Common/function.php
 - Linux crontab 查看所有用户的crontab任务
			
查看所有用户的crontab任务 - mlzhu007的专栏 - CSDN博客 https://blog.csdn.net/mlzhu007/article/details/81662091 以roo ...
 - linux安装Elasticsearch详细步骤
			
坑都已经踩好了 照着步骤一次成功 不多废话 走起 # ## 安装java运行环境 elasticsearch是用Java实现的 跑elasticsearch必须要有jre支持 所以必须先安装jre ...
 - Spark学习(3)  SparkSQL
			
什么事sparkSQL Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象叫做DataFrame并且作为分布式SQL查询引擎的作用, 它是将Spark SQL转换成RDD ...
 - Delphi百度文字识别【支持通用文字识别、身份证识别、银行卡识别、驾驶证识别、行驶证识别、车牌识别等功能】
			
作者QQ:(648437169) 点击下载➨Delphi百度文字识别 百度api文档 [Delphi百度文字识别]支持 通用文字识别.通用文字识别(高精度版).通用文字识别(含位置信 ...