新建 T1、T2、T3 三个线程,如何保证它们按顺序执行
在Java中,可以使用线程的join()方法来保证线程的顺序执行。join()方法会将线程暂停,直到调用该方法的线程结束执行为止。
以下是创建T1、T2、T3三个线程,并按顺序执行的示例代码:
public class Main {public static void main(String[] args) {Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("T1 is running");}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {try {t1.join(); // 等待T1线程执行完成} catch (InterruptedException e) {e.printStackTrace();}System.out.println("T2 is running");}});Thread t3 = new Thread(new Runnable() {@Overridepublic void run() {try {t2.join(); // 等待T2线程执行完成} catch (InterruptedException e) {e.printStackTrace();}System.out.println("T3 is running");}});t1.start();t2.start();t3.start();}
}
在上述代码中,我们创建了三个线程T1、T2、T3,并分别使用join()方法来保证它们按顺序执行。在T2的run()方法中,首先调用t1.join(),表示等待T1线程执行完成后再执行。在T3的run()方法中,同样调用t2.join(),表示等待T2线程执行完成后再执行。
当main方法中的t1.start()、t2.start()、t3.start()被调用时,线程T1、T2、T3会同时开始执行。然而,由于在T2、T3线程中调用了join()方法,它们会暂停执行,直到被等待的线程执行完成。
这样,就可以保证T1、T2、T3三个线程按顺序执行。输出结果将是:
T1 is running
T2 is running
T3 is running
注意:在实际开发中,线程的执行顺序会受到许多因素的影响,例如线程调度、时间片分配等。使用join()方法可以保证指定线程执行完成后再执行下一个线程,但不能保证线程的绝对顺序执行。
怎么控制同一时间只有 3 个线程运行
在Java中,可以使用Semaphore(信号量)来控制同时运行的线程数量。Semaphore是一种并发控制工具,它可以指定同时能够访问某个资源或者执行某个操作的线程数量。
下面是一个例子,说明如何使用Semaphore来实现同一时间只有3个线程运行:
import java.util.concurrent.Semaphore;public class ThreadControlExample {public static void main(String[] args) {// 创建Semaphore对象,指定允许同时运行的线程数量为3Semaphore semaphore = new Semaphore(3);// 创建10个线程并启动for (int i = 0; i < 10; i++) {Thread thread = new MyThread(semaphore, i);thread.start();}}static class MyThread extends Thread {private Semaphore semaphore;private int threadId;public MyThread(Semaphore semaphore, int threadId) {this.semaphore = semaphore;this.threadId = threadId;}public void run() {try {System.out.println("Thread " + threadId + " is waiting");// 获取Semaphore许可semaphore.acquire();System.out.println("Thread " + threadId + " is running");// 模拟线程的执行Thread.sleep(2000);System.out.println("Thread " + threadId + " is finished");} catch (InterruptedException e) {e.printStackTrace();} finally {// 释放Semaphore许可semaphore.release();}}}
}
上述代码中,我们创建了一个Semaphore对象,并将允许同时运行的线程数量设置为3。然后我们创建了10个线程,并在每个线程中先调用acquire()
方法获取Semaphore的许可,然后执行具体的业务逻辑,最后在finally
块中调用release()
方法释放Semaphore的许可。
在运行过程中,最多只会有3个线程同时运行,其余线程会等待直到有空闲的许可。当一个线程完成任务并释放许可之后,等待的线程中会有一个线程获取到许可并开始执行任务。
需要注意的是,在acquire()
方法和release()
方法之间的代码需要保证原子性,以避免释放了没有获取到的许可。
总结
Semaphore是Java中的一个并发工具,用于控制多个线程的访问某个共享资源的数量。下面是关于Semaphore对象的总结:
-
Semaphore是一个计数信号量,用来表示当前可用的资源数量。它有一个初始值,每次调用acquire()方法时,Semaphore的计数减1;每次调用release()方法时,Semaphore的计数加1。
-
Semaphore可以用来限制某个资源的并发访问数量。比如,如果有3个资源可供访问,可以创建一个初始值为3的Semaphore对象,然后每个线程在访问资源之前都要调用acquire()方法获取许可,访问完之后调用release()方法释放许可。
-
Semaphore可以用来控制线程的执行顺序。比如,可以创建一个初始值为0的Semaphore对象,然后某个线程在执行到某个特定点时调用acquire()方法获取许可,然后等待其他线程执行完毕后再继续执行。
-
Semaphore还可以用来实现互斥锁的功能。通过创建一个初始值为1的Semaphore对象,并在临界区的开始和结束时分别调用acquire()和release()方法,可以实现只有一个线程能够访问临界区的效果。
-
Semaphore还有一个特殊的构造函数Semaphore(int permits, boolean fair),其中permits参数表示初始许可的数量,fair参数表示是否使用公平性策略。如果fair参数为true,Semaphore会按照线程的到达顺序来获取许可。