【问题标题】:How can I get a single thread to wait instead of my whole program?如何让单个线程而不是整个程序等待?
【发布时间】:2012-07-22 15:22:13
【问题描述】:

我正在编写一个服务器程序,当 ArrayList 中有客户端时,它会通过 RMI 通知客户端。

但是我无法停止和恢复通知客户端的线程。

这是我的代码:

package eu.craenhals;

import java.awt.Dimension;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.JFrame;
import javax.swing.JTextArea;

import java.awt.BorderLayout;

public class Server extends JFrame {
    private static final long serialVersionUID = 1L;
    private JTextArea textArea;
    private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy - HH:mm:ss");
    private ServerImpl server;
    private ServerThread thread;

    public Server() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setTitle("Server");
    setSize(new Dimension(521, 333));

    textArea = new JTextArea();
    textArea.setEditable(false);
    getContentPane().add(textArea, BorderLayout.CENTER);

    initialize();
    log("Server opgestart op poort 9878");
    }

    private void initialize() {
    log("Server wordt opgestart");
    try {
        Registry registry = LocateRegistry.createRegistry(9878);
        server = new ServerImpl();
        registry.rebind("server", server);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
    Object lock = new Object();
    thread = new ServerThread(lock);
    thread.start();
    synchronized(lock) {
        try {
        lock.wait();
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
    }
    }

    public static void main(String[] args) {
    Server server = new Server();
    server.setVisible(true);
    }

    private void log(String message) {
    textArea.append(dateFormat.format(new Date()) + " - " + message + "\n");
    }

    class ServerImpl extends UnicastRemoteObject implements ServerInterface {
    private static final long serialVersionUID = 1L;
    private ArrayList<ClientInterface> clients = new ArrayList<ClientInterface>();

    protected ServerImpl() throws RemoteException {
        super();
    }

    private void notifyClients() {
        log("Clients verwittigen");
        for (ClientInterface client : clients) {
        try {
            client.notify("Interface van client " + client.getName() + " updaten");
        } catch (RemoteException e) {
            log(e.getMessage());
        }
        }
    }

    @Override
    public void addClient(ClientInterface client) throws RemoteException {
        if (clients.contains(client)) {
        log("Client '" + client.getName() + "' niet toegevoegd, want bestaat al");
        throw new RemoteException("Client niet toegevoegd, want bestaat al");
        }
        clients.add(client);
        log("Client '" + client.getName() + "' toegevoegd");
    }

    @Override
    public void removeClient(ClientInterface client) throws RemoteException {
        boolean isVerwijderd = clients.remove(client);
        if (isVerwijderd) {
        log("Client '" + client.getName() + "' verwijderd");
        } else {
        log("Client '" + client.getName() + "' niet verwijderd, want bestond niet");
        throw new RemoteException("Client niet verwijderd, want bestond niet");
        }

    }
    }

    class ServerThread extends Thread {
    private final Object lock;

    public ServerThread(Object lock) {
        this.lock = lock;
    }

    public void flag() {
        synchronized (lock) {
        System.out.println("Before Wait");
        try {
            lock.wait();
            System.out.println("After Being Notified");
        } catch (InterruptedException ex) {
            System.out.println("Thread interrupted");
        }
        }
    }

    public void unflag() {
        synchronized (lock) {
        System.out.println("Before Notify All");
        lock.notifyAll();
        System.out.println("After Notify All Method Call");
        }
    }

    public void run() {
        while (true) {
        System.out.println("In serverthread");
        server.notifyClients();
        synchronized (lock) {
            try {
            lock.wait(5000);
            } catch (InterruptedException ex) {
            }
        }
        }
    }
    }
}

我有一个 ServerThread 变量,我在初始化方法中启动该线程。

但是,当我在线程变量上调用 flag 时,我的整个程序都在等待,而不仅仅是线程。我该如何解决这个问题?

【问题讨论】:

    标签: java multithreading wait notify


    【解决方案1】:
    1. wait() 只有在另一个线程调用时才能重新获得锁定 notify() 在同一个对象上 wait() 调用。

    2. 现在根据上面的说法,我会尽力纠正你的问题。

      • 首先在类范围内创建Object lock = new Object(),以便其他线程可以看到它。

      • wait() and notify() 必须在同步块中,所以将你的 notify 与要释放锁的对象放在一个同步块中。

        示例:

        synchronized(lock) {
           lock.notify();
        }
        

    【讨论】:

    • 不,不起作用。当我将锁对象放在类范围内并尝试在同步块中调用锁上的等待方法时,我的服务器框架没有出现,所以他没有停止新线程,而是停止了正在构建我的线程JFrame.
    • 让你的 EDT (Event Dispatcher Thead) 只处理 GUI 的构建,不要涉及到其他线程,public static void main(String[] args){ EventQueue.invokeLater(new Runnable(){ myframe.setVisible(true); }); // Now from here do call other thread }
    • 嗨,格雷,您的回答很好,但大部分内容都是粗体字。乍一看很难用肉眼把握。我认为斜体字体比较合适。
    猜你喜欢
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    • 2017-09-28
    • 1970-01-01
    • 2016-05-01
    • 1970-01-01
    相关资源
    最近更新 更多