下面的课程会在特定的时间间隔内更新地图。
public class CheckerThread extends Thread {
private volatile HashMap<String, Integer> map = new HashMap<>();
@Override
public void run() {
while (true) {
updateMap();
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
// Do something
}
}
}
private void updateMap() {
HashMap<String, Integer> localMap = new HashMap<>();
int count = 0;
while (count < 10) {
localMap.put(count + "a", count);
count++;
}
this.map = localMap;
}
public Map<String, Integer> getMap() {
return this.map;
}
}
下面的类调用方法getMap()来获取Map。我需要确保列表完全更新,然后才能在类#34; CheckerThread&#34;中返回地图。该方法应该等到地图更新。
public class GetterThread extends Thread {
private final CheckerThread checkerThread;
public GetterThread(final CheckerThread checkerThread) {
this.checkerThread = checkerThread;
}
@Override
public void run() {
System.err.println(this.checkerThread.getMap());
}
}
另一个Main创建线程。
public class MainThread extends Thread {
public static void main(final String[] args) throws InterruptedException {
int i = 0;
GetterThread[] getterThreads = new GetterThread[5];
CheckerThread checkerThread = new CheckerThread();
checkerThread.start();
while (i < 5) {
getterThreads[i] = new GetterThread(checkerThread);
getterThreads[i].start();
Thread.sleep(1000);
i++;
}
}
}
}
答案 0 :(得分:1)
线程的想法是可以的,但还不够(大多数是因为线程在完成工作后不会返回任何内容......)如果你仍想使用线程,那么你将以等待/加入/通知方法......
您可以代替thread --> runnable
使用task --> callable
,
Callables 是类固醇上的线程,你可以在 ExecutorService 中执行它们并等到作业完成后得到一个结果,让你知道一切是否正常或不!!
以此为例,查阅文档以获取更多信息:
public class _Foo {
public static void main(String... args) throws InterruptedException, ExecutionException {
ExecutorService exService = Executors.newSingleThreadExecutor();
FutureTask<Boolean> futureTask = new FutureTask<>(new MapCleaner());
exService.execute(futureTask);
System.out.println("Was everything ok??: " + futureTask.get());
}
}
class MapCleaner implements Callable<Boolean> {
@Override
public Boolean call() {
try {
Thread.sleep(3000);
} catch (InterruptedException ex) {
System.out.println(ex);
}
return System.currentTimeMillis() % 2 == 0;
}
}
答案 1 :(得分:0)
public class MyCallable implements Callable<Map<String, Integer>> {
private volatile HashMap<String, Integer> map = new HashMap<>();
private boolean wait = true;
public void call() {
while (wait) {
updateMap();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
return map;
}
private void updateMap() {
HashMap<String, Integer> localMap = new HashMap<>();
int count = 0;
while (count < 10) {
localMap.put(count + "a", count);
}
this.map = localMap;
wait = false;
}
}
然后打电话给未来
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Map<String, Integer>> future = executor.submit(new MyCallable());
// Future.get() waits for task to get completed
Map<String, Integer> myMap = fut.get();
答案 2 :(得分:0)
根据您的示例,我认为您应该使用BlockingQueue
。将元素放入“checker”线程的队列中,并在“getter”线程中使用阻塞等待读取它们。这很简单,非常干净,不需要太多更改。
队列不仅可以解决您的同步问题,还可以解决计时问题。无论你的线程运行在哪个顺序,你的getter线程总是等待数据可用,然后返回。它几乎是防弹的。
顺便说一句,你的检查线程中有一个错误。你把10个元素放到了地图中,但是你永远不会增加count
,所以循环永远不会退出(它会将无数个元素放入地图中,最终会出现内存不足的错误)。
此外,永远不要抓住并忽略InterruptedException
。如果你被打断,你几乎总想退出你的线程。 C.F. Brian Goetz的书 Java Concurrency in Practice 了解更多。
public class SimpleThreading
{
public static void main(String[] args) throws InterruptedException {
MainThread.main(args);
}
}
class MainThread extends Thread
{
public static void main( final String[] args )
throws InterruptedException
{
int i = 0;
GetterThread[] getterThreads = new GetterThread[ 5 ];
CheckerThread checkerThread = new CheckerThread();
checkerThread.start();
while( i < 5 ) {
getterThreads[i] = new GetterThread( checkerThread );
getterThreads[i].start();
Thread.sleep( 1000 );
i++;
}
}
}
class GetterThread extends Thread
{
private final CheckerThread checkerThread;
public GetterThread( final CheckerThread checkerThread )
{
this.checkerThread = checkerThread;
}
@Override
public void run()
{
try {
System.out.println("waiting..." + checkerThread.getQueue() );
System.err.println( this.checkerThread.getQueue().take() );
} catch( InterruptedException ex ) {
// exit on interrupt
}
}
}
class CheckerThread extends Thread
{
private HashMap<String, Integer> map;
private final BlockingQueue<Map<String,Integer>> queue =
new LinkedBlockingQueue<>();
@Override
public void run()
{
while( true )
try {
updateMap();
queue.put( map );
System.out.println( "Added " + map );
Thread.sleep( 1000 );
} catch( InterruptedException e ) {
return; // exit on interrupt
}
}
private void updateMap()
{
HashMap<String, Integer> localMap = new HashMap<>();
int count = 0;
while( count < 10 )
localMap.put( count + "a", count++ );
this.map = localMap;
}
public BlockingQueue<Map<String, Integer>> getQueue()
{
return queue;
}
}