如何使用java.util.concurrent挂起线程?

如何使用java.util.concurrent挂起线程?,java,multithreading,java.util.concurrent,Java,Multithreading,Java.util.concurrent,我到处都找过了。如何通过代码挂起/暂停它,直到我使用任何java.util.concurrent方法/对象调用它来唤醒它?我有一个简单的线程运行方法: 当我按下按钮时,它停止然后开始,但问题是,当我再次启动它时,会出现异常。我希望它像在媒体播放器中一样播放/暂停 Exception in thread "AWT-EventQueue-0" java.lang.IllegalMonitorStateException 完整工作代码(例外情况除外): 一种方法是使用CyclicBarrier(来

我到处都找过了。如何通过代码挂起/暂停它,直到我使用任何
java.util.concurrent
方法/对象调用它来唤醒它?我有一个简单的线程运行方法:

当我按下按钮时,它停止然后开始,但问题是,当我再次启动它时,会出现异常。我希望它像在媒体播放器中一样播放/暂停

Exception in thread "AWT-EventQueue-0" java.lang.IllegalMonitorStateException
完整工作代码(例外情况除外):

一种方法是使用CyclicBarrier(来自java.util.concurrent),用两个“party”参数化它

在屏障上调用
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();
        }
    }
}

我知道你需要一个按钮来启动和停止线程。因此,基本上,您需要在
actionPerformed()
中获取锁,查找事物的状态,操纵状态,告诉等待的实体有什么变化,然后释放所有锁

Runnable
线程(由于缺少标签)应该基本保持不变,但应该在循环中检查
条件
,以避免出现
signalAll()
唤醒且
条件
仍然不符的情况。(
signal()
signalAll()
不能保证在释放锁后立即同步,因此可能已经发生了对
actionPerformed()
的两次调用)


将“真”更改为“假”terminate@sanket:这不会使它暂停。它将终止它。为什么不使用wait()/notify()?为什么依赖java.util.concurrent?没有挂起/恢复。使用同步结构,如信号量、倒计时闩锁、ReentrantLock和friends。@p000ison wait/notify在大多数情况下都不是一个好主意。它隐藏了对等方之间的连接,通常情况下,你会在等待中锁定一个线程,你不知道应该由谁向其发送通知。如果你只有一个线程,然后挂起它,那么应用程序中不会发生任何事情-它将永远挂起。你有两个线程是隐式的。作为可运行的JPanel应该位于另一个线程内,在主线程和swing线程外。但是,无论哪个实体实际启动线程,都应该是触发Runnable的“wake”事件的实体,也许您应该将线程创建启动代码添加到您的问题中,以获得更好的清晰度,因此click事件是一个单独的事件线程。为了使代码正常工作,您必须从它内部调用lock,现在它只调用unlock,但线程从未获得它。这就是为什么你会得到非法监视器的原因,因为你实际上是在试图释放一个你从未有过的条目(至少乍一看是这样),在这里使用@Stevie的代码而不是锁和条件,会得到你想要的。这里有两个线程(Runnable线程和Swing事件线程)。@Yoda我强烈推荐Brian Goetz的书《实践中的Java并发性》——它会让你再次快乐起来。取决于运气,它有时会冻结20秒。但有时工作很快。嗯,这可能是事件线程。但是锁的获取应该非常快,除非日历在你按下按钮的时候更新。你在那里睡觉,这就是为什么:)线程一直都在持有锁,所以你不能在这段时间内处理按钮按下。首先我不知道为什么会有睡眠,所以我把它留下了,但我建议把它完全去掉,这样它就可以每隔500-1500毫秒打印一次区域数据,而不是以光速打印。
 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();
        }
    }

}
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();
        }
    }
}
    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();
        }
    }

}