加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

多个线程顺序打印不同字符abcdefg(利用线程池实现多线程)

发布时间:2020-12-15 08:01:41 所属栏目:Java 来源:网络整理
导读:下面实现多线程顺序打印字符"abcdefg"; 实现Runnable接口: /** * @author : rhyme * @date: 2019-08-17 14:39 * @topic: "Runnable" * @description: "每个线程通过sign表示需要打印的字符数组下标,index表示将要打印的字符数组的下标" */ public class P

下面实现多线程顺序打印字符"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线程池、如何停止一个线程

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读