ExecutorService 两个线程池 执行顺序
时间: 2024-07-27 18:00:53 浏览: 194
`ExecutorService` 是 Java 中用于管理并发任务的工具,它提供了一种线程复用的方式,可以创建并控制线程池。当你有多个线程任务需要执行时,而不是每次都新建线程,可以创建多个 `ExecutorService` 实例来代表不同的线程池。
如果同时使用两个独立的 `ExecutorService`,它们的执行顺序并不是预设的。每个线程池内部有自己的工作队列,当提交任务到各自的线程池时,任务会先进入对应线程池的工作队列,然后由线程池中的线程按其调度策略来执行。
例如,如果你有一个固定大小的 `ThreadPoolExecutor` 和一个无界大小的 `ScheduledThreadPool`,它们可能会有不同的执行策略:
1. 固定线程池通常使用先进先出(FIFO)策略,新加入的任务会在队列满时阻塞。
2. 调度线程池可能会有定时或周期性的任务调度,不是按照任务添加的顺序执行。
所以,无法直接预测这两个线程池任务的执行顺序。如果你想控制特定任务的执行顺序,可以考虑使用 `Future` 来获取任务结果,并通过 `Future.get()` 或者自定义排序规则来手动调整执行顺序。
相关问题
定义一个线程池,2个核心,队列中最多只能存30个任务
线程池是一种管理和重复利用线程的方法,能够在多个任务之间轮流使用池中的空闲线程,从而减少系统的开销和资源浪费。对于题目要求的线程池,具体实现如下:
1. 创建两个核心线程,在池中持续运行,以便之后分配任务。
2. 创建一个任务队列,使得任务可以在队列中等待执行。任务队列应该是一个先进先出的队列,当队列中的任务被取出时,应该按照任务到达的时间进行排序。
3. 在队列中最多存储30个任务,在超过30个任务时,新的任务将不能加入队列中,而是等待队列中有空余。
4. 当线程池中的线程处于空闲状态时,线程池应该分配一个任务给该线程,以便其执行任务。如果线程池中不再有空闲线程,任务应该等待,直到有可用线程。
5. 当一个线程执行完任务时,它应该从任务队列中取出下一个任务进行执行。
6. 当线程池中的线程数超过2个核心线程时,多出来的线程应该丢弃,否则会浪费系统资源。
下面是一个简单实现的代码示例:
```
import java.util.concurrent.*;
public class ThreadPoolDemo {
public static void main(String[] args) {
// 线程池核心线程数为2,最大线程数为2,任务队列最大存储数为30
ExecutorService pool = new ThreadPoolExecutor(2, 2, 0, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(30));
// 创建30个任务,加入任务队列
for (int i = 1; i <= 30; i++) {
final int index = i;
pool.execute(new Runnable() {
public void run() {
System.out.println("任务" + index + "开始执行");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务" + index + "执行完成");
}
});
}
// 关闭线程池
pool.shutdown();
}
}
```
在本示例中,线程池通过ThreadPoolExecutor实现,核心线程数为2,最大线程数为2,任务队列最大存储数为30。随后,创建30个任务,加入任务队列并执行。每个任务都会sleep 2s,以便在控制台中看到执行顺序。最后,调用ThreadPoolExecutor的shutdown方法关闭线程池。
package 操作系统实验二; import java.util.concurrent.*; class PrintTask implements Runnable { private char ch; private Semaphore currentSemaphore; private Semaphore nextSemaphore; public PrintTask(char ch, Semaphore currentSemaphore, Semaphore nextSemaphore) { this.ch = ch; this.currentSemaphore = currentSemaphore; this.nextSemaphore = nextSemaphore; } public void run() { try { for (int i = 0; i < 3; i++) { currentSemaphore.acquire(); System.out.print(ch); nextSemaphore.release(); } } catch (InterruptedException e) { e.printStackTrace(); } } } public class Main { public static void main(String[] args) { Semaphore semaphoreA = new Semaphore(1); Semaphore semaphoreB = new Semaphore(0); PrintTask printA = new PrintTask('A', semaphoreA, semaphoreB); PrintTask printB = new PrintTask('B', semaphoreB, semaphoreA); ExecutorService executorService = Executors.newFixedThreadPool(2); // 顺序1:AAAB executorService.execute(printA); executorService.execute(printA); executorService.execute(printA); executorService.execute(printB); // 顺序2:BBAA //executorService.execute(printB); //executorService.execute(printB); //executorService.execute(printA); //executorService.execute(printA); // 顺序3:AABA //executorService.execute(printA); //executorService.execute(printA); //executorService.execute(printB); //executorService.execute(printA); // 顺序4:ABAA //executorService.execute(printA); //executorService.execute(printB); //executorService.execute(printA); //executorService.execute(printA); executorService.shutdown(); } }
这是一个 Java 语言编写的操作系统实验二的代码。这个代码实现了两个线程交替打印字符 A 和字符 B,实现了多线程之间的同步。具体来说,这个代码中使用了 Semaphore 类来实现不同线程之间的同步。Semaphore 是一个计数信号量,用于控制并发访问的线程数。其中,Semaphore(1) 表示只有一个线程可以获得该 Semaphore,Semaphore(0) 表示初始时没有线程可以获得该 Semaphore。在这个代码中,PrintTask 类实现了 Runnable 接口,表示可以被一个线程执行。在 run() 方法中,先通过 acquire() 方法获得 currentSemaphore,表示当前线程可以执行,然后打印字符 ch,最后通过 release() 方法释放 nextSemaphore,表示下一个线程可以执行了。在 main() 方法中,创建了两个 Semaphore 对象 semaphoreA 和 semaphoreB,并分别传递给两个 PrintTask 对象 printA 和 printB。然后通过 ExecutorService 来启动线程池,并按照不同的顺序执行不同的打印操作。最后,调用 executorService.shutdown() 方法关闭线程池。
阅读全文
相关推荐
















