我正在尝试准备简单的程序,它允许用户创建很少的并发工作任务。没什么特别的。每个任务从值1开始,并在达到最大值时添加另一个任务(每个任务获得不同的最大值)。然后任务通知,已达到指定值并停止。所有任务必须包含在ArrayList中,我所做的。我需要提供允许(在每个时刻)
的方法我宁愿避免使用gui,因为我的教授并不需要。我已经参与,但我不知道如何打印列表的所有元素(TASK_LIST)并停止个别任务。
MAIN.java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
Task t1 = new Task("Task 1", 2);
Task t2 = new Task("Task 2", 20);
Task t3 = new Task("Task 3", 5);
exec.execute(t1);
exec.execute(t2);
exec.execute(t3);
//showTASK_LIST();
}
}
TASK.java
import java.util.ArrayList;
import java.util.List;
class Task implements Runnable {
String TASK_NAME;
int TASK_RESULT;
int TASK_GOAL;
String TASK_STATUS;
static List<Task> TASK_LIST = new ArrayList<Task>();
public Task(String name, int goal) {
this.TASK_NAME = name;
this.TASK_GOAL = goal;
this.TASK_STATUS = "INACTIVE";
TASK_LIST.add(this);
}
public void run() {
TASK_STATUS="ACTIVE";
System.out.println(TASK_NAME + " starts.");
while (TASK_RESULT != TASK_GOAL){
//if (Thread.currentThread().isInterrupted()) return;
TASK_RESULT++;
System.out.println(TASK_NAME + " " + TASK_RESULT);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.yield();
}
System.out.println("===========================================\n" +
TASK_NAME + " has been completed. Final result = " + TASK_GOAL +
"\n===========================================" );
setTASK_STATUS("COMPLETED");
System.out.println(TASK_LIST.size());
}
//Method to check current result
public int getTASK_RESULT() {
return TASK_RESULT;
}
//Method to check current status
public String getTASK_STATUS() {
return TASK_STATUS;
}
//Method to change result
public void setTASK_STATUS(String status) {
TASK_STATUS = status;
}
//This part doesnt work
public showTASK_LIST(){
for(int i = 0; i <= TASK_LIST.size(); i++){
System.out.println(TASK_LIST.get(i).TASK_NAME);
}
}
}
这就是它在这一刻的表现。
答案 0 :(得分:1)
您需要使showTASK_LIST()
静态。然后,您可以使用Task.showTASK_LIST();
如下所示
public static void showTASK_LIST(){
for(int i = 0; i <= TASK_LIST.size(); i++){
System.out.println(TASK_LIST.get(i).TASK_NAME);
}
Task.showTASK_LIST();//goes in your main method to show the tasks
我运行代码时得到的结果在上面的代码中产生了一个indexOutOfBounds异常。这是一个简单的解决方案。
将您的for循环更改为此
for(int i = 0; i < TASK_LIST.size(); i++)// changed <= to <
只有3个任务,&lt; =上升到导致问题的第四个任务
我得到了这个输出
Task 1 starts.
Task 3 starts.
Task 3 1
Task 1
Task 2
Task 3
Task 2 starts.
Task 1 1
Task 2 1
Task 3 2
Task 1 2
Task 2 2
Task 3 3
===========================================
Task 1 has been completed. Final result = 2
===========================================
Task 2 3
3
Task 3 4
Task 2 4
Task 2 5
Task 3 5
Task 2 6
===========================================
Task 3 has been completed. Final result = 5
===========================================
3
Task 2 7
Task 2 8
Task 2 9
Task 2 10
Task 2 11
Task 2 12
Task 2 13
Task 2 14
Task 2 15
Task 2 16
Task 2 17
Task 2 18
Task 2 19
Task 2 20
===========================================
Task 2 has been completed. Final result = 20
===========================================
3
答案 1 :(得分:1)
您的代码存在线程安全问题,因为您尝试从多个线程读取/写入共享资源(在本例中为Task对象)上的值:
您正在从一个线程更改任务状态(写入)并尝试从不同的线程(读取)读取它,这是主线程就是这种情况:
Task.showTASK_LIST()
同样的问题还有:
//Method to check current result
public int getTASK_RESULT() {
return TASK_RESULT;
}
//Method to check current status
public String getTASK_STATUS() {
return TASK_STATUS;
}
您可以在以下位置阅读有关Java并发和线程安全的信息: https://en.wikipedia.org/wiki/Thread_safety https://docs.oracle.com/javase/tutorial/essential/concurrency/
我将在重复使用代码的同时提供我自己的实现,但在此之前,在您查看代码之前几个主题演讲:
StatusChangeListener
public interface StatusChangeListener {
void statusChanged(String oldStatus, String newStatus);
}
主要强>
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
//manage your tasks list here
ArrayList<Task> tasks = new ArrayList<>();
Task t1 = new Task("Task 1", 2);
Task t2 = new Task("Task 2", 20);
Task t3 = new Task("Task 3", 5);
tasks.add(t1);
tasks.add(t2);
tasks.add(t3);
//add status change listener to be notified for t1 status changes
t1.addStatusChangeListener(new MyListener());
System.out.println("tasks = " + tasks);
//use submit instead of execute
Future<Integer> future1 = executor.submit(t1);
System.out.println("task 1 is done = " + future1.isDone());
Future<Integer> future2 = executor.submit(t2);
Future<Integer> future3 = executor.submit(t3);
//cancel task 3
future3.cancel(true);
try {
System.out.println("future 1 result= " + future1.get());
System.out.println("future 2 result= " + future2.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
//you can do the same with the progress. e.g. add progress listener
private static class MyListener implements StatusChangeListener{
@Override
public void statusChanged(String oldStatus, String newStatus) {
System.out.println(String.format("Thread : %s status changed from %s to %s", Thread.currentThread(), oldStatus, newStatus));
}
}
}
<强>任务强>
import java.util.concurrent.Callable;
class Task implements Callable<Integer> {
//can be replaced by enum
private String TASK_STATUS;
private String TASK_NAME;
private int TASK_RESULT;
private int TASK_GOAL;
private StatusChangeListener statusChangeListener;
public Task(String name, int goal) {
this.TASK_NAME = name;
this.TASK_GOAL = goal;
this.TASK_STATUS = "INACTIVE";
}
//private Method to change result
private void setTASK_STATUS(String newStatus) {
String oldStatus = TASK_STATUS;
TASK_STATUS = newStatus;
//notify status changes
if (statusChangeListener != null)
statusChangeListener.statusChanged(oldStatus, newStatus);
}
@Override
public Integer call() throws Exception {
setTASK_STATUS("ACTIVE");
System.out.println(TASK_NAME + " starts.");
while (TASK_RESULT != TASK_GOAL) {
//if (Thread.currentThread().isInterrupted()) return;
TASK_RESULT++;
System.out.println(TASK_NAME + " " + TASK_RESULT);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thread.yield();
}
System.out.println("===========================================\n" +
TASK_NAME + " has been completed. Final result = " + TASK_GOAL +
"\n===========================================");
setTASK_STATUS("COMPLETED");
return TASK_RESULT;
}
public void addStatusChangeListener(StatusChangeListener statusChangeListener) {
this.statusChangeListener = statusChangeListener;
}
}