下面实现多线程顺序打印字符"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; public PrintRunnable(String chars, int sign) { this.chars = chars.toCharArray(); this.sign = sign; } @Override public void run() { while (true) { // 为了结合线程池shutdownNow方法设置中断interrupt停止线程 if (Thread.currentThread().isInterrupted()) { break; } synchronized (PrintRunnable.class) { if (index % chars.length == sign) { System.out.printf("ThreadName : %s is printing (%c)\n", Thread.currentThread().getName(), chars[sign]); index++; } } } } }
这里实现Runnable接口,两个重要的属性sign和index;
sign表示当前线程打印的那个字符在字符数组中的下标;
index表示移动字符下标打印, index % chars.length(重要,顺序打印的核心实现)的值表示需要打印的字符的下标,当一个字符被打印,index++;
chars表示一个字符数组;
线程如果表示为被设为中断,则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 { 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,这里主要是为了将正在运行的线程设置中断标志位,死循环利用中断标志位结束循环。
shutdownNow 方法:此方法执行后不得向线程池再提交任务,如果有空闲线程则销毁空闲线程,取消所有位于阻塞队列中的任务,并将其放入 List容器,作为返回值;取消正在执行的线程(实际上仅仅是设置正在执行线程的中断标志位,调用线程的 interrupt 方法来中断线程)。
启动main方法,多个线程按顺序打印"abcdefg",3s后结束,执行结果部分截图如下:
当然也可以通过"等待-唤醒"机制实现,如用一个ReentrantLock对象的的newCondition()方法创建多个Condition对象。
JAVA线程状态、线程START方法源码、多线程、JAVA线程池、如何停止一个线程
多个线程顺序打印不同字符abcdefg(利用线程池实现多线程)
原文:https://www.cnblogs.com/theRhyme/p/11369069.html