线程新手:并发加入一个又一个线程
Thread Newbie: Joining thread one after another with concurrent
我想运行一个接一个地发帖。
Java 8 有没有其他的马拉松比赛方式?
不使用 ExecuterService
:
public class Marathon {
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+ " is running... " + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
};
Thread t1 = new Thread(task, "Mary");
Thread t2 = new Thread(task, "David");
t1.start();
t1.join(100);
t2.start();
}
}
输出:
Mary is running... 0
David is running... 0
Mary is running... 1
David is running... 1
...
以下代码不适用于马拉松:
public class Marathon2 {
public static void main(String[] args)
throws InterruptedException, ExecutionException, TimeoutException {
ExecutorService service = null;
Runnable task = () -> {
try {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()
+ " is running... " + i);
}
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
}
};
try {
service = Executors.newFixedThreadPool(4);
Future<?> job1 = service.submit(task);
job1.get(500, TimeUnit.MILLISECONDS);
Future<?> job2 = service.submit(task);
} finally {
if (service != null)
service.shutdown();
}
}
}
输出:
pool-1-thread-1 是 运行ning... 0
...
pool-1-thread-1 是 运行ning... 9
pool-1-thread-2 是 运行ning... 0
...
pool-1-thread-2 是 运行ning... 9
ExecuterService 可以吗?
预期:
pool-1-thread-1 is running... 0
pool-1-thread-2 is running... 0
...
pool-1-thread-1 is running... 9
pool-1-thread-2 is running... 9
无需处理任何线程或直接执行程序,您可以使用 CompletableFuture
Runnable runnable = () -> System.out.println("hi");
Runnable runnable1 = () -> System.out.println("there");
CompletableFuture<Void> all = CompletableFuture.runAsync(runnable).thenRun(runnable1);
all.whenComplete((x,th) -> {
System.out.println("both done");
});
请注意,这将使用通用的 ForkJoin 池,但您仍然可以提供自己的池。
两个 class 不是在做同样的事情。您可能可以通过仔细比较它们自己找到解决方案。首先,您是否确切知道您的第一个 class(马拉松)是如何运作的?特别是,您认为以下行的作用是什么?
t1.join(100);
刚刚启动运行的线程t1刚刚进入一个每200毫秒计数一次的循环。 join(100) 调用只会导致当前(主)线程等待 100 毫秒。将该行替换为这一行,您将获得完全相同的结果:
Thread.sleep(100);
现在主线程已经休眠了 100 毫秒,它启动线程 t2。现在两个线程 运行 并行,每 200 毫秒两个线程输出一行,第二个线程延迟 100 毫秒,以便它们均匀交错。
现在让我们看看您的第二种方法,Marathon2。与第一个 class 的一些差异是显而易见的:
- Runnable 中的休眠在循环外,而不是在循环内。
- Runnable 中的睡眠只有 100 毫秒,而不是 200。
- 主线程中的最长等待时间是 500 毫秒,而不是 100。
- Future.get 方法导致 TimeoutException 而不是继续。无论如何,我们可以简单地将此调用替换为睡眠,因为这就是第一个 class 所做的全部。
因此,消除差异,我们得到以下 Marathon2 class,其行为方式与另一个 class(Marathon)类似,具有交错线程:
public class Marathon2 {
public static void main(String[] args)
throws InterruptedException, ExecutionException, TimeoutException {
ExecutorService service = null;
Runnable task = () -> {
try {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()
+ " is running... " + i);
TimeUnit.MILLISECONDS.sleep(200);
}
} catch (InterruptedException e) {
}
};
try {
service = Executors.newFixedThreadPool(4);
Future<?> job1 = service.submit(task);
TimeUnit.MILLISECONDS.sleep(100);
Future<?> job2 = service.submit(task);
} finally {
if (service != null)
service.shutdown();
}
}
}
我想运行一个接一个地发帖。
Java 8 有没有其他的马拉松比赛方式?
不使用 ExecuterService
:
public class Marathon {
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+ " is running... " + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
};
Thread t1 = new Thread(task, "Mary");
Thread t2 = new Thread(task, "David");
t1.start();
t1.join(100);
t2.start();
}
}
输出:
Mary is running... 0
David is running... 0
Mary is running... 1
David is running... 1
...
以下代码不适用于马拉松:
public class Marathon2 {
public static void main(String[] args)
throws InterruptedException, ExecutionException, TimeoutException {
ExecutorService service = null;
Runnable task = () -> {
try {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()
+ " is running... " + i);
}
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
}
};
try {
service = Executors.newFixedThreadPool(4);
Future<?> job1 = service.submit(task);
job1.get(500, TimeUnit.MILLISECONDS);
Future<?> job2 = service.submit(task);
} finally {
if (service != null)
service.shutdown();
}
}
}
输出:
pool-1-thread-1 是 运行ning... 0
...
pool-1-thread-1 是 运行ning... 9
pool-1-thread-2 是 运行ning... 0
...
pool-1-thread-2 是 运行ning... 9
ExecuterService 可以吗?
预期:
pool-1-thread-1 is running... 0
pool-1-thread-2 is running... 0
...
pool-1-thread-1 is running... 9
pool-1-thread-2 is running... 9
无需处理任何线程或直接执行程序,您可以使用 CompletableFuture
Runnable runnable = () -> System.out.println("hi");
Runnable runnable1 = () -> System.out.println("there");
CompletableFuture<Void> all = CompletableFuture.runAsync(runnable).thenRun(runnable1);
all.whenComplete((x,th) -> {
System.out.println("both done");
});
请注意,这将使用通用的 ForkJoin 池,但您仍然可以提供自己的池。
两个 class 不是在做同样的事情。您可能可以通过仔细比较它们自己找到解决方案。首先,您是否确切知道您的第一个 class(马拉松)是如何运作的?特别是,您认为以下行的作用是什么?
t1.join(100);
刚刚启动运行的线程t1刚刚进入一个每200毫秒计数一次的循环。 join(100) 调用只会导致当前(主)线程等待 100 毫秒。将该行替换为这一行,您将获得完全相同的结果:
Thread.sleep(100);
现在主线程已经休眠了 100 毫秒,它启动线程 t2。现在两个线程 运行 并行,每 200 毫秒两个线程输出一行,第二个线程延迟 100 毫秒,以便它们均匀交错。
现在让我们看看您的第二种方法,Marathon2。与第一个 class 的一些差异是显而易见的:
- Runnable 中的休眠在循环外,而不是在循环内。
- Runnable 中的睡眠只有 100 毫秒,而不是 200。
- 主线程中的最长等待时间是 500 毫秒,而不是 100。
- Future.get 方法导致 TimeoutException 而不是继续。无论如何,我们可以简单地将此调用替换为睡眠,因为这就是第一个 class 所做的全部。
因此,消除差异,我们得到以下 Marathon2 class,其行为方式与另一个 class(Marathon)类似,具有交错线程:
public class Marathon2 {
public static void main(String[] args)
throws InterruptedException, ExecutionException, TimeoutException {
ExecutorService service = null;
Runnable task = () -> {
try {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()
+ " is running... " + i);
TimeUnit.MILLISECONDS.sleep(200);
}
} catch (InterruptedException e) {
}
};
try {
service = Executors.newFixedThreadPool(4);
Future<?> job1 = service.submit(task);
TimeUnit.MILLISECONDS.sleep(100);
Future<?> job2 = service.submit(task);
} finally {
if (service != null)
service.shutdown();
}
}
}