可以指定线程个数和执行轮次的Java多线程交替执行示例(核心:判断是否为最后一轮,如果是,则跳出循环)
引言
在多线程编程中,经常会遇到需要多个线程交替执行的场景。本文将通过一个简单的示例,展示如何使用Java实现指定线程个数和指定轮次的交替执行任务。
**核心:**通过if((step + THREAD_NUM - index - 1) / THREAD_NUM == EXEC_ROUND)判断是否为最后一轮,如果是,则跳出循环。即计算截至到目前当前线程执行了多少轮,等于EXEC_ROUND则说明是最后一轮,(当前执行次数+提前几次结束)/线程组长度=当前执行轮次,提前几次结束=线程组长度-索引-1
示例代码
首先,我们来看一段实现两个线程交替执行的Java代码:
public class TwoThreadExecAlternatelyV2 {
// 目标:两个线程循环打印指定轮次
// 思路:每个线程尝试获取锁,获取锁后执行打印,然后再释放锁;关键是怎么才能确保两个线程交替获取锁
// 优化点:1.将重复共性的代码逻辑抽取出来 2.支持指定线程数 3.在共性代码中实现:1) 按指定顺序执行多个线程 2)最后一轮按线程执行顺序依次跳出任务的逻辑
private static final Object obj = new Object();//共享资源,即被加锁的对象
private static final int EXEC_ROUND = 100;//执行轮次,所有线程均执行一遍,为一轮
private static final int THREAD_NUM = 5;//线程个数
private static Thread[] threadGroup;//线程组
private static int step = 0;//计步器,每当每个线程执行一次任务,则加1
public static void task(){
while(true){
String threadName = Thread.currentThread().getName();
int index = Integer.parseInt(threadName.substring(threadName.length()-1));//创建线程时线程名称的最后一位保存的就是线程在线程组中的索引位置
if(step%THREAD_NUM==index){//通过线程在线程组中的索引对线程组长度取余,决定线程组内每个线程的执行时机,即执行顺序
synchronized(obj){//显示地获取锁
obj.notifyAll();//唤醒其他处于等待状态的线程,但是不释放锁,其他线程依然获取不到锁
step++;
System.out.println(threadName+",step:"+(step)+",index:"+(index));
if((step+THREAD_NUM-index-1)/THREAD_NUM==EXEC_ROUND){//到最后一轮跳出任务,计算截至到目前当前线程执行了多少轮,等于EXEC_ROUND则说明是最后一轮,(当前执行次数+提前几次结束)/线程组长度=当前执行轮次,提前几次结束=线程组长度-索引-1
break;
}
try { obj.wait(); } catch (InterruptedException e) {e.printStackTrace(); }//将本线程置为等待状态
}
}//隐式地释放锁
}
}
public static void exec(){
threadGroup = new Thread[THREAD_NUM];
for(int i = 0; i <THREAD_NUM; i++ ){
threadGroup[i] = new Thread(()->{task();},"printThread"+i);
threadGroup[i].start();
}
}
public static void main(String[] args) throws InterruptedException{
exec();
}
}
代码解析
-
共享资源:使用一个
Object
对象作为锁,控制线程的同步。 -
执行轮次:定义了一个常量
EXEC_ROUND
,表示每个线程需要执行的轮次。 -
线程组:定义了一个线程数组
threadGroup
,用于存储和管理线程。 -
计步器:使用一个静态变量
step
作为计步器,记录当前执行的步骤。 -
任务方法:
task
方法中,每个线程通过判断step
的值来决定是否执行任务。如果当前线程应该执行,则进入同步块,执行打印操作,并唤醒其他线程。 -
执行逻辑:通过
if((step + THREAD_NUM - index - 1) / THREAD_NUM == EXEC_ROUND)
判断是否为最后一轮,如果是,则跳出循环。 -
线程启动:在
exec
方法中,创建并启动线程。 -
主方法:在
main
方法中调用exec
方法,启动线程组。
运行结果
运行上述代码,可以看到线程按照指定的顺序交替执行任务,直到完成指定的轮次。
总结
通过这个示例,我们可以看到Java多线程编程中如何通过同步机制实现线程的交替执行。这种方法在实际开发中非常有用,特别是在需要控制线程执行顺序的场景中。希望这个示例对你有所帮助!
以上就是关于Java多线程交替执行的一个简单示例及其解析。希望对你有所帮助!如果你有任何问题或建议,欢迎在评论区讨论。