Hello All(第一篇文章)!
首先我要说我在Java编程方面还是比较新的(C ++是我的强项)
如果已经回答了这个问题,请指出正确的方向,但我的搜索技巧还没有达到我想要的效果。我遇到的问题是我的消费者线程之间的同步,而不是我的生产者/消费者
之间的同步我的任务包括从生产者线程中查找素数候选者,而不是使用多个消费者线程来检查每个候选人的有效性:
使用多个线程,1个生产者线程将“候选人”放入一个名为 prime_candidates 的arraylist(必须是arraylist),消费者除了从arraylist中获取并检查
消费者检查,如果它是素数,他们将素数放入他们自己的arraylist prime_list
60秒后, prime_list 被写入文件并继续
我已成功将 prime_candidates 与使用者(检查)线程同步。但我不能为我的生活弄清楚如何同步消费者线程产生的ArrayLists。它们都是自己创建的,并且使用我从Producer / Consumer中使用的同步方法不起作用。
生产线
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class GenerateThread implements Runnable{
// MAIN ARRAY LIST THAT STORES THE NUMBERS WHICH COULD BE CONSIDERED PRIME CANDIDATES
private final ArrayList<PrimeCandidate> prime_candidates = new ArrayList();
private boolean alive = true; // MAIN VARIABLE THAT WILL CONTINUE TO RUN THE THREAD
private boolean toggle = true; // VARIABLE THAT PAUSES THE PRODUCER
// START: FOR PANEL LAYOUT //
JPanel genPanel = new JPanel();
JPanel lastPane = new JPanel();
JLabel lastOutput = new JLabel();
JPanel queuePane = new JPanel();
JLabel queueOutput = new JLabel();
JLabel headLabel = new JLabel("Generate Thread");
JLabel lastLabel = new JLabel("Last");
JLabel queueLabel = new JLabel("Queue");
JButton pauseButton = new JButton("Pause");
JButton terminateButton = new JButton("Terminate");
// END: FOR PANEL LAYOUT //
// DEFAULT CONSTRUCTOR, DOESN'T REALLY DO MUCH
GenerateThread(){ System.out.println("Creating Generator");}
public JPanel createPanel()
{
// TO SET THE BLACK BORDER AROUND THE PANELS HOLDING CURRENT SIZE AND
// PRIME CANDIDATE
lastPane.setBorder(BorderFactory.createLineBorder(Color.black));
queuePane.setBorder(BorderFactory.createLineBorder(Color.black));
// ADD LISTENER TO TERMINATE THREAD
terminateButton.addActionListener(new terminateListener());
// ADD LISTENER TO PAUSE THREAD
pauseButton.addActionListener(new pauseListener());
lastPane.add(lastOutput);
queuePane.add(queueOutput);
genPanel.add(headLabel);
genPanel.add(lastLabel);
genPanel.add(lastPane);
genPanel.add(queueLabel);
genPanel.add(queuePane);
genPanel.add(pauseButton);
genPanel.add(terminateButton);
return genPanel;
}
@Override
public void run()
{
long i = 3;
while(alive)
{
if(toggle)
{
if(i % 2 == 1)
if(!TestForPrime.isDividableBy3(BigInteger.valueOf(i)))
{
addToArrayList(BigInteger.valueOf(i));
lastOutput.setText(BigInteger.valueOf(i).toString());
queueOutput.setText(BigInteger.valueOf(prime_candidates.size()).toString());
}
i++;
}
if(!toggle)continueNotifying();
}
while(!alive){continueNotifying();}
}
// ADDS NEW ITEM TO ARRAYLIST AND NOTIFYS ALL THREADS DEPENDENT ON ARRAYLIST
public synchronized void addToArrayList(BigInteger b)
{
prime_candidates.add(new PrimeCandidate(b, new Date()));
notify();
}
// CONTINUES NOTIFYING OTHER THREADS WHEN PAUSED OR TERMINATED SINCE THEY WILL
// NOT RUN UNLESS THEY HAVE BEEN GIVEN THE 'GO AHEAD' (NOTIFY())
public synchronized void continueNotifying()
{
queueOutput.setText(BigInteger.valueOf(prime_candidates.size()).toString());
notify();
}
// USED BY THE OTHER THREADS TO GET ITEMS FROM THE ARRAY LIST, THREADS DELETE
// THE VARIABLE THAT THEY GRAB, ESSENTIALLY CUTTING THE ARRAY LIST DOWN EVERY
// TIME
public synchronized PrimeCandidate getFromArrayList() throws InterruptedException
{
wait(); //Keeps thread from adding more to list while others are grabbing it
PrimeCandidate returnCandidate = new PrimeCandidate(prime_candidates.get(0));
prime_candidates.remove(0);
return returnCandidate;
}
// LISTENER THAT WILL KILL THE THREAD PRIME CANDIDATE PRODUCER
// ALSO GREYS OUT BOTH BUTTONS TO SHOW THREAD IS DEAD
class terminateListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
terminateButton.setEnabled(false);
pauseButton.setEnabled(false);
alive = false;
}
}
// LISTENER THAT WILL TEMPORARILY STOP THE PRODUCER
class pauseListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
if(toggle)
pauseButton.setText("Start");
if(!toggle)
pauseButton.setText("Pause");
toggle = !toggle;
}
}
}
消费者线程
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class CheckThread implements Runnable{
private final GenerateThread generated;
private ArrayList<Primes> prime_list = new ArrayList();
//private CopyOnWriteArrayList<Primes> prime_list = new CopyOnWriteArrayList();
private final String threadName;
private boolean alive = true;
private boolean toggle = true;
private Date timeFetched;
private Date timeFound;
private Primes currentPrime;
// START: FOR PANEL LAYOUT //
JPanel genPanel = new JPanel();
JPanel lastPane = new JPanel();
JLabel lastOutput = new JLabel();
JPanel queuePane = new JPanel();
JLabel queueOutput = new JLabel();
JLabel headLabel = new JLabel("Generate Thread");
JLabel lastLabel = new JLabel("Last");
JLabel queueLabel = new JLabel("In Work");
JButton pauseButton = new JButton("Pause");
JButton terminateButton = new JButton("Terminate");
// END: FOR PANEL LAYOUT //
CheckThread(GenerateThread gen, String name, int priority)
{
generated = gen;
threadName = name;
headLabel.setText(name);
System.out.println("Creating | " + name);
if(priority == 0)
{
System.out.println(name + " Is writing thread");
final Timer t = new Timer(10000, new writeToFileTimer());
t.start();
}
}
public JPanel createPanel()
{
lastPane.setBorder(BorderFactory.createLineBorder(Color.black));
lastPane.setMinimumSize(new Dimension(200,100));
queuePane.setBorder(BorderFactory.createLineBorder(Color.black));
terminateButton.addActionListener(new terminateListener());
pauseButton.addActionListener(new pauseListener());
lastPane.add(lastOutput);
queuePane.add(queueOutput);
genPanel.add(headLabel);
genPanel.add(lastLabel);
genPanel.add(lastPane);
genPanel.add(queueLabel);
genPanel.add(queuePane);
genPanel.add(pauseButton);
genPanel.add(terminateButton);
lastOutput.setIgnoreRepaint(true);
return genPanel;
}
class writeToFileTimer implements ActionListener
{
@Override
public void actionPerformed(ActionEvent event)
{
try{ writeToFile();}catch (InterruptedException e) { System.out.println("WTF");}
}
}
@Override
public void run()
{
while(alive)
{
try
{
if(toggle)
{
PrimeCandidate recieved = new PrimeCandidate(generated.getFromArrayList());
timeFetched = new Date();
//queueOutput.setText(recieved.getCandidate().toString());
if(TestForPrime.isPrime(recieved.getCandidate()))
{
lastOutput.setText(recieved.getCandidate().toString());
timeFound = new Date();
String temp = "" + prime_list.size();
queueOutput.setText(temp);
addToArrayList(new Primes(recieved.getCandidate(),recieved.getTimeStamp(), timeFetched));
}
}
} catch (InterruptedException e) {}
}
}
class terminateListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
terminateButton.setEnabled(false);
pauseButton.setEnabled(false);
alive = false;
}
}
class pauseListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
if(toggle)
pauseButton.setText("Start");
if(!toggle)
pauseButton.setText("Pause");
toggle = !toggle;
}
}
// ADDS NEW ITEM TO ARRAYLIST AND NOTIFYS ALL THREADS DEPENDENT ON ARRAYLIST
public synchronized void addToArrayList(Primes primeFound)
{
prime_list.add(primeFound);
}
// USED BY THE OTHER THREADS TO GET ITEMS FROM THE ARRAY LIST, THREADS DELETE
// THE VARIABLE THAT THEY GRAB, ESSENTIALLY CUTTING THE ARRAY LIST DOWN EVERY
// TIME
public synchronized void writeToFile() throws InterruptedException
{
wait();
try
{
File statText = new File("prime_numbers.txt");
FileOutputStream is = new FileOutputStream(statText);
OutputStreamWriter osw = new OutputStreamWriter(is);
Writer writ = new BufferedWriter(osw);
while(!prime_list.isEmpty())
{
writ.append(prime_list.get(0).toString());
prime_list.remove(0);
}
writ.close();
headLabel.setText(threadName);
} catch (IOException e) {System.err.println(" failed to write to Test.txt");}
notify();
}
}
我知道代码编写错误但是当我执行此任务时,我不断碰壁并从头开始重写我的代码并最终停止了关怀。有谁知道如何在消费者线程中轻松同步我的所有prime_list Arraylist。如果您没有注意到我构建了每个数组列表,那么我可以简单地将每个线程/面板添加到主框架中。它在获取和检查质数方面完美无缺,但我目前的头痛是写一个文件所有线程一起产生的。我可以将每个线程单独写入文件,但最终每次都会相互写入
答案 0 :(得分:0)
如果我理解正确,您需要每60秒将所有消费者的累积素数写入文件。
现在您使用prime_list作为实例变量,因此多个线程将拥有自己的prime_list。您可以将prime_list标记为static,并且访问这些的方法也是静态的。在这些方法中,代码必须在synchronized块中。
这不是最好的设计。如果我从头开始写作,我将不会使用这个设计,但它会对你有用。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class CheckThread implements Runnable{
private final GenerateThread generated;
private static ArrayList<Primes> prime_list = new ArrayList();
//private CopyOnWriteArrayList<Primes> prime_list = new CopyOnWriteArrayList();
private final String threadName;
private boolean alive = true;
private boolean toggle = true;
private Date timeFetched;
private Date timeFound;
private Primes currentPrime;
// START: FOR PANEL LAYOUT //
JPanel genPanel = new JPanel();
JPanel lastPane = new JPanel();
JLabel lastOutput = new JLabel();
JPanel queuePane = new JPanel();
JLabel queueOutput = new JLabel();
JLabel headLabel = new JLabel("Generate Thread");
JLabel lastLabel = new JLabel("Last");
JLabel queueLabel = new JLabel("In Work");
JButton pauseButton = new JButton("Pause");
JButton terminateButton = new JButton("Terminate");
// END: FOR PANEL LAYOUT //
CheckThread(GenerateThread gen, String name, int priority)
{
generated = gen;
threadName = name;
headLabel.setText(name);
System.out.println("Creating | " + name);
if(priority == 0)
{
System.out.println(name + " Is writing thread");
final Timer t = new Timer(10000, new writeToFileTimer());
t.start();
}
}
public JPanel createPanel()
{
lastPane.setBorder(BorderFactory.createLineBorder(Color.black));
lastPane.setMinimumSize(new Dimension(200,100));
queuePane.setBorder(BorderFactory.createLineBorder(Color.black));
terminateButton.addActionListener(new terminateListener());
pauseButton.addActionListener(new pauseListener());
lastPane.add(lastOutput);
queuePane.add(queueOutput);
genPanel.add(headLabel);
genPanel.add(lastLabel);
genPanel.add(lastPane);
genPanel.add(queueLabel);
genPanel.add(queuePane);
genPanel.add(pauseButton);
genPanel.add(terminateButton);
lastOutput.setIgnoreRepaint(true);
return genPanel;
}
class writeToFileTimer implements ActionListener
{
@Override
public void actionPerformed(ActionEvent event)
{
try{ writeToFile();}catch (InterruptedException e) { System.out.println("WTF");}
}
}
@Override
public void run()
{
while(alive)
{
try
{
if(toggle)
{
PrimeCandidate recieved = new PrimeCandidate(generated.getFromArrayList());
timeFetched = new Date();
//queueOutput.setText(recieved.getCandidate().toString());
if(TestForPrime.isPrime(recieved.getCandidate()))
{
lastOutput.setText(recieved.getCandidate().toString());
timeFound = new Date();
String temp = "" + prime_list.size();
queueOutput.setText(temp);
addToArrayList(new Primes(recieved.getCandidate(),recieved.getTimeStamp(), timeFetched));
}
}
} catch (InterruptedException e) {}
}
}
class terminateListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
terminateButton.setEnabled(false);
pauseButton.setEnabled(false);
alive = false;
}
}
class pauseListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
if(toggle)
pauseButton.setText("Start");
if(!toggle)
pauseButton.setText("Pause");
toggle = !toggle;
}
}
// ADDS NEW ITEM TO ARRAYLIST AND NOTIFYS ALL THREADS DEPENDENT ON ARRAYLIST
public static void addToArrayList(Primes primeFound)
{
synchronized(prime_list) { // Added this
prime_list.add(primeFound);
}
}
// USED BY THE OTHER THREADS TO GET ITEMS FROM THE ARRAY LIST, THREADS DELETE
// THE VARIABLE THAT THEY GRAB, ESSENTIALLY CUTTING THE ARRAY LIST DOWN EVERY
// TIME
public static void writeToFile() throws InterruptedException
{
synchronized(prime_list) { // Added this
try
{
File statText = new File("prime_numbers.txt");
FileOutputStream is = new FileOutputStream(statText);
OutputStreamWriter osw = new OutputStreamWriter(is);
Writer writ = new BufferedWriter(osw);
for(int i=0;i<prime_list.size();i++) {
writ.append(prime_list.get(i));
}
prime_list.clear();
writ.close();
headLabel.setText(threadName);
} catch (IOException e) {System.err.println(" failed to write to Test.txt");}
}
}
}