- 题目要求
- 3个线程打印1-100的整数,每个线程打印3个数字,结果要求是有序输出 线程1:1,2,3,... 线程2:4,5,6,... 线程3:7,8,9
- 很ugly的思路
- 创建三个线程,每个线程依赖一个信号量,并在处理完之后释放下一个信号量,实现线程之间的同步
- 线程内部一直循环,直到某一线程到达指定的数字,直接调用System.exit(0),退出JVM虚拟机
- 缺点:可扩展性差,如果要增加线程数,还要多加Semaphore和run方法代码
package com.example.demo;
import java.util.concurrent.Semaphore;
public class PrintNum {
static int num = 0;
static int i=1;
public static void main(String[] args) {
num = 100;
Semaphore semaphore1 = new Semaphore(1);
Semaphore semaphore2 = new Semaphore(0);
Semaphore semaphore3 = new Semaphore(0);
new Thread(()->{
while (true){
try {
semaphore1.acquire();
printTask();
semaphore2.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()->{
while (true){
try {
semaphore2.acquire();
printTask();
semaphore3.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(()->{
while (true){
try {
semaphore3.acquire();
printTask();
semaphore1.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
static void printTask() {
System.out.print(Thread.currentThread().getName()+": ");
int count = 0;
while(count <=2) {
System.out.print(i++ + " ");
if(i == num+1) {
System.exit(0);
}
count++;
}
System.out.println();
}
}
- 改进思路
- 使用固定的线程池
- 创建一个记录线程的数组列表,当第一次运行的时候将该线程添加到列表中,然后使用自旋,直到轮到自己在数组中的index号,再执行任务
- 优点:可以指定任意个线程大小
- 缺点:使用数组,自己建立同步关系,代码不易懂~
package com.example.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class PrintNum {
static int threadNum = 5; // 有几个线程执行
static int num = 100; // 数的最大值
static int currPrintNum = 1; // 当前输出的数
static List<Thread> threadList; // 顺序存储Thread的列表
static int currThreadIndex = 0; // 一个指向需要执行的Thread的指针
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(threadNum);
threadList= new ArrayList<>();
for(int i = 0; i < threadNum ;i++) {
executorService.execute(new PrintRunnable());
}
}
static class PrintRunnable implements Runnable {
@Override
public void run() {
Thread currThread = Thread.currentThread();
if(!threadList.contains(currThread)) {
synchronized (PrintRunnable.class) { // 使用类锁
currThread.setName("线程" + (currThreadIndex+1));
threadList.add(currThread);
myTask();
if(threadNum-1 == currThreadIndex) {
currThreadIndex = 0;
} else {
currThreadIndex++;
}
}
}
while(true) { // myTask() 调用System.exit() 所有的线程结束循环
// 使用自旋
while( threadList.indexOf(currThread) != currThreadIndex) {
}
synchronized (PrintRunnable.class) {
myTask();
if(threadNum-1 == currThreadIndex) {
currThreadIndex = 0;
} else {
currThreadIndex++;
}
}
}
}
}
static void myTask() {
System.out.print(Thread.currentThread().getName()+": ");
int count = 0;
while(count <=2) {
System.out.print(currPrintNum++ + " ");
if(currPrintNum == num+1) {
System.exit(0);
}
count++;
}
System.out.println();
}
}