我有一个代表world
的科目
public class WorldLifecycle {
private ExecutorService executorService;
public void startWorld() {
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(),
r -> {
String id = ((IdentifiableRunnable) r).getId();
return new Thread(r, id);
});
}
public void bringLife(LivingPerson ... people) {
Arrays.stream(people).forEach(executorService::submit);
}
public void endWorld() {
executorService.shutdownNow();
try {
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
System.err.println("Failed to finish thread executor!");
}
}
}
每个LivingPerson
都像这样
public class LivingPerson implements IdentifiableRunnable {
// investigate global world variable
private boolean isRunning = true;
private final StatefulPerson person;
public LivingPerson(StatefulPerson person) {
this.person = person;
}
@Override
public void run() {
System.out.println("Initial state: person=" + person.getRawPerson());
while (isRunning) { // for now forever
try {
Thread.sleep(1000); // do transition every 1 seconds
LifeState state = person.nextState();
System.out.println(getPerson().getName() + " " + state.getActionLabel());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("End state: person=" + person.getRawPerson());
}
@Override
public String getId() {
Person person = getPerson();
return person.getId() + " - " + person.getName();
}
@Override
public void terminate() {
isRunning = false;
}
// returns clone instead of existing
private Person getPerson() {
return person.getRawPerson();
}
}
我想使用人员的姓名和唯一标识符来命名每个线程。
IdentifiableRunnable
是一个简单的界面
public interface IdentifiableRunnable extends Runnable {
String getId();
void terminate();
}
我像这样初始化所有东西
WorldLifecycle world = new WorldLifecycle();
LivingPerson male = createPerson("John", 40, Gender.MALE);
LivingPerson female = createPerson("Helen", 25, Gender.FEMALE);
System.out.println("Starting world...");
world.startWorld();
world.bringLife(male, female);
// just wait
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("Destroying world...");
world.endWorld();
但是当我尝试运行它时,我得到了错误
Exception in thread "main" java.lang.ClassCastException: java.util.concurrent.ThreadPoolExecutor$Worker cannot be cast to com.lapots.breed.lifecycle.api.Ide
ntifiableRunnable
at com.lapots.breed.lifecycle.WorldLifecycle.lambda$startWorld$0(WorldLifecycle.java:14)
at java.util.concurrent.ThreadPoolExecutor$Worker.<init>(ThreadPoolExecutor.java:612)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:925)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1357)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at com.lapots.breed.lifecycle.WorldLifecycle.bringLife(WorldLifecycle.java:20)
at com.lapots.breed.Sandbox.main(Sandbox.java:23)
看来identifiableRunnable
中没有我的ThreadFactory
。
如何解决?
答案 0 :(得分:1)
如果您使用调试器跟踪库调用,您会注意到newThread
方法的调用方式如下:
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
因此它传递了Worker
类的实例,显然不能将其强制转换为您的IdentifiableRunnable
。
要并行执行流,应使用ForkJoinPool
在本帖子中的描述,第一个答案Custom thread pool in Java 8 parallel stream
顺便说一句,这是您如何压缩帖子中的代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.stream.Stream;
public class Main {
interface TestInterface extends Runnable{
default String getId() {
return "2";
}
}
static class TestClass implements TestInterface {
@Override
public void run() {
System.out.println("TEST");
}
}
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
@Override
public Thread newThread(final Runnable r) {
String id = ((TestInterface)r).getId();
Thread t = new Thread(r, id);
t.setDaemon(true);
return t;
}
});
Stream.of(new TestClass(),new TestClass(),new TestClass(),new TestClass()).forEach(exec::submit);
}
}