按照顺序执行
要保证新建的T1、T2、T3三个线程按顺序执行,可以使用Java的CountDownLatch类。以下是一个示例:
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
Thread t1 = new Thread(() -> {
System.out.println("T1开始执行");
// 执行任务
System.out.println("T1执行完毕");
latch.countDown();
});
Thread t2 = new Thread(() -> {
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T2开始执行");
// 执行任务
System.out.println("T2执行完毕");
});
Thread t3 = new Thread(() -> {
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T3开始执行");
// 执行任务
System.out.println("T3执行完毕");
});
t1.start();
t2.start();
t3.start();
}
}
在这个示例中,我们创建了一个CountDownLatch实例,并将其计数器设置为1。然后,我们创建了三个线程T1、T2和T3。在每个线程的任务执行完毕后,我们调用latch.countDown()方法将计数器减1。在T2和T3线程中,我们使用latch.await()方法等待计数器变为0,然后再继续执行任务。这样,我们就可以确保T1、T2和T3线程按顺序执行。
按照指定顺序执行
要保证新建的T1、T2、T3三个线程按指定顺序执行,可以使用Java的Thread类的join()方法。以下是一个示例:
public class Main {
public static void main(String[] args) throws InterruptedException {
// 创建并启动第一个线程
Thread t1 = new Thread(() -> {
System.out.println("T1开始执行");
// 执行任务
System.out.println("T1执行完毕");
});
t1.start();
// 等待第一个线程执行完毕
t1.join();
// 创建并启动第二个线程
Thread t2 = new Thread(() -> {
System.out.println("T2开始执行");
// 执行任务
System.out.println("T2执行完毕");
});
t2.start();
// 等待第二个线程执行完毕
t2.join();
// 创建并启动第三个线程
Thread t3 = new Thread(() -> {
System.out.println("T3开始执行");
// 执行任务
System.out.println("T3执行完毕");
});
t3.start();
// 等待第三个线程执行完毕
t3.join();
}
}
在这个示例中,我们首先创建并启动了第一个线程T1,然后使用t1.join()方法等待T1执行完毕。接着,我们创建并启动第二个线程T2,同样使用t2.join()方法等待T2执行完毕。最后,我们创建并启动第三个线程T3,使用t3.join()方法等待T3执行完毕。这样,我们就可以确保T1、T2和T3线程按指定顺序执行。
多线程之间如何进行通信?
在Java中,多线程之间可以通过共享内存、wait()/notify()方法、join()方法等方式进行通信。
以共享内存为例,新建T1、T2、T3三个线程,可以使用一个共享变量来作为线程间通信的媒介。例如:
public class Main {
private static int count = 0; // 共享变量
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
count--;
}
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("count=" + count);
}
}
});
t1.start();
t2.start();
t3.start();
// 等待所有线程执行完毕
t1.join();
t2.join();
t3.join();
}
}
在这个示例中,我们创建了三个线程t1、t2和t3,它们分别对共享变量count进行加一、减一和输出操作。由于count是共享变量,因此这三个线程可以对其进行读写操作,从而实现线程间的通信。
怎么控制同一时间只有 2 个线程运行?
在Java中,可以使用Semaphore类来实现同一时间只有2个线程运行的控制。
Semaphore类是一个计数信号量,用来控制同时访问特定资源的线程数量。它常用于实现资源池,防止过度占用资源。
以下是一个示例:
import java.util.concurrent.Semaphore;
public class Main {
private static Semaphore semaphore = new Semaphore(2); // 创建一个Semaphore对象,并设置最大并发数为2
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire(); // 获取许可
System.out.println("T1 is running");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放许可
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire(); // 获取许可
System.out.println("T2 is running");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放许可
}
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire(); // 获取许可
System.out.println("T3 is running");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放许可
}
}
});
t1.start();
t2.start();
t3.start();
}
}
在这个示例中,我们创建了一个Semaphore对象,并设置了最大并发数为2。然后,我们在每个线程的run方法中调用了semaphore.acquire()来获取一个许可,如果没有可用的许可,那么这个线程将会被阻塞,直到有其他线程释放了一个许可。最后,在每个线程的finally块中,我们调用了semaphore.release()来释放一个许可,这样其他等待的线程就可以获取到许可并开始执行了。