我到处找过了。如何通过代码挂起/暂停它,直到我使用任何java.util.concurrent方法/对象调用它来唤醒它?我有一个简单的线程和run方法:
当我按下按钮,它就会停止,然后开始,但问题是,当我再次启动它时,我会得到异常。我要它播放/暂停,就像在媒体播放器里一样。
Exception in thread "AWT-EventQueue-0" java.lang.IllegalMonitorStateException完整的工作代码(例外情况除外):
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class Window extends JFrame {
ThreadPanel leftPanel, rightPanel;
Thread leftThread, rightThread;
public Window() {
super("StopResume");
}
public void createGUI() {
setLayout(new GridLayout());
add(leftPanel = new ThreadPanel());
add(rightPanel = new ThreadPanel());
leftThread = new Thread(leftPanel);
rightThread = new Thread(rightPanel);
leftThread.start();
rightThread.start();
setSize(800, 600);
setVisible(true);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
int confirmed = JOptionPane.showConfirmDialog(null, "Zamknąć", "Potwierdzenie", JOptionPane.OK_CANCEL_OPTION);
if (confirmed == JOptionPane.OK_OPTION) {
dispose();//tu podmienic kod
System.exit(1);
}
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Window().createGUI();
}
});
}
} import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class ThreadPanel extends JPanel implements Runnable {
public static final String SUSPENDED = "GO", RUNNING = "SUSPEND";
JTextArea txt;
JButton ppButton;
DateFormat dateFormat;
Lock lock;
Condition cond;
boolean running;
public ThreadPanel() {
super();
createGUI();
dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
lock = new ReentrantLock();
cond = lock.newCondition();
running = true;
}
public void createGUI() {
setLayout(new BorderLayout());
JScrollPane jsp = new JScrollPane(txt = new JTextArea(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
add(jsp, BorderLayout.CENTER);
add(ppButton = new JButton(RUNNING), BorderLayout.SOUTH);
ppButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
System.out.println(1);
if (running) {
running = false;
ppButton.setText(SUSPENDED);
} else {
running = true;
ppButton.setText(RUNNING);
lock.unlock();
}
lock.lock();
if (!running) {
cond.signalAll();
}
lock.unlock();
}
});
}
@Override
public void run() {
while (true) {
lock.lock();
try {
if (!running)
cond.await();
} catch (Exception e) {
e.printStackTrace();
}
Calendar cal = Calendar.getInstance();
txt.append("\n" + dateFormat.format(cal.getTime()));
try {
Thread.sleep((long) (Math.random() * 1001 + 500));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(2);
lock.unlock();
}
}
}发布于 2014-01-04 13:24:47
我看到你想要一个按钮来启动和停止线程。因此,基本上您需要在actionPerformed()中获取锁,查找事物的状态,操作状态,告诉等待实体某些更改,然后释放所有锁。
Runnable线程(由于缺少标签)应该保持大部分不变,但应该检查循环中的Condition,以避免signalAll()唤醒,而Condition仍然不符合或错误的情况。(signal()和signalAll()不能保证在释放锁后立即同步,因此可能已经发生了对actionPerformed()的2次调用)。
public void createGUI() {
setLayout(new BorderLayout());
JScrollPane jsp = new JScrollPane(txt = new JTextArea(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
add(jsp, BorderLayout.CENTER);
add(ppButton = new JButton(RUNNING), BorderLayout.SOUTH);
ppButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// This is where we acquire the lock to safely look at the state
lock.lock();
System.out.println(1);
// Manipulate the state
if (running) {
running = false;
ppButton.setText(SUSPENDED);
} else {
running = true;
ppButton.setText(RUNNING);
}
// Signal that this conditional changed (is either true or false now)
cond.signalAll();
// Release the lock so other entities can go forward
lock.unlock();
}
});
}
@Override
public void run() {
while (true) {
lock.lock();
try {
// This should block until this condition is true with a loop
while (!running)
cond.await();
} catch (Exception e) {
e.printStackTrace();
}
Calendar cal = Calendar.getInstance();
txt.append("\n" + dateFormat.format(cal.getTime()));
// No need to sleep()
System.out.println(2);
lock.unlock();
}
}
}发布于 2014-01-04 12:58:46
我认为您所要求的一种方法是使用CyclicBarrier (来自java.util.concurrent),将其参数化为两个“各方”。
在屏障上调用await的第一个线程将被挂起/阻塞,直到第二个线程也调用await,此时两个线程都可以继续执行。
下面是一个简单的代码示例:
import java.util.concurrent.CyclicBarrier;
public class Test {
public static void main(String[] args) {
// a barrier requiring two threads to call await before
// any thread can proceed past the barrier
final CyclicBarrier barrier = new CyclicBarrier(2);
new Thread(){
@Override
public void run() {
try {
// do some stuff
System.out.println("in thread, before the barrier");
// calling await blocks until two threads
// (this one and one other) have called await
barrier.await();
// do some more stuff
System.out.println("in thread, after the barrier");
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
try {
System.out.println("main thread, before barrier");
// calling await blocks until two threads
// (this one and one other) have called await
barrier.await();
System.out.println("main thread, after barrier");
} catch (Exception exc) {
exc.printStackTrace();
}
}
}https://stackoverflow.com/questions/20921083
复制相似问题