Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何让一个线程而不是整个程序等待?_Java_Multithreading_Wait_Notify - Fatal编程技术网

Java 如何让一个线程而不是整个程序等待?

Java 如何让一个线程而不是整个程序等待?,java,multithreading,wait,notify,Java,Multithreading,Wait,Notify,我正在编写一个服务器程序,当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

我正在编写一个服务器程序,当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) {
            }
        }
        }
    }
    }
}
package eu.craenhals;
导入java.awt.Dimension;
导入java.rmi.RemoteException;
导入java.rmi.registry.LocateRegistry;
导入java.rmi.registry.registry;
导入java.rmi.server.UnicastRemoteObject;
导入java.text.simpleDataFormat;
导入java.util.ArrayList;
导入java.util.Date;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入javax.swing.JFrame;
导入javax.swing.JTextArea;
导入java.awt.BorderLayout;
公共类服务器扩展了JFrame{
私有静态最终长serialVersionUID=1L;
私人JTEXTEXTAREA textArea;
私有SimpleDataFormat dateFormat=新SimpleDataFormat(“dd/MM/yyyy-HH:MM:ss”);
私有服务器impl服务器;
私有服务器线程;
公共服务器(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle(“服务器”);
设置尺寸(新尺寸(521333));
textArea=新的JTextArea();
textArea.setEditable(false);
getContentPane().add(textArea,BorderLayout.CENTER);
初始化();
日志(“服务器opgestart op poort 9878”);
}
私有void初始化(){
日志(“服务器wordt optart”);
试一试{
Registry=LocateRegistry.createRegistry(9878);
server=newserverimpl();
registry.rebind(“server”,server);
}捕获(远程异常){
e、 printStackTrace();
}
对象锁=新对象();
线程=新服务器线程(锁);
thread.start();
已同步(锁定){
试一试{
lock.wait();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
公共静态void main(字符串[]args){
服务器=新服务器();
setVisible(true);
}
私有无效日志(字符串消息){
textArea.append(dateFormat.format(new Date())+“-”+message+“\n”);
}
类ServerImpl扩展UnicastRemoteObject实现ServerInterface{
私有静态最终长serialVersionUID=1L;
私有ArrayList客户端=新ArrayList();
受保护的ServerImpl()引发RemoteException{
超级();
}
私有客户机(){
日志(“客户verwittigen”);
for(客户端界面客户端:客户端){
试一试{
client.notify(“Interface van client”+client.getName()+“updaten”);
}捕获(远程异常){
日志(如getMessage());
}
}
}
@凌驾
public void addClient(ClientInterface客户端)引发RemoteException{
if(clients.contains(client)){
日志(“Client'”+Client.getName()+“'niet toegevogd,want bestaat al”);
抛出新的RemoteException(“客户端niet-toegevoegd,want-bestaat al”);
}
客户。添加(客户);
日志(“Client'+Client.getName()+“'toegevoegd”);
}
@凌驾
public void removeClient(ClientInterface客户端)引发RemoteException{
布尔值isVerwijderd=clients.remove(client);
如果(isVerwijderd){
日志(“Client'+Client.getName()+“'verwijderd”);
}否则{
日志(“Client'”+Client.getName()+“'niet verwijderd,want bestond niet”);
抛出新的RemoteException(“客户机niet verwijderd,want bestond niet”);
}
}
}
类ServerThread扩展线程{
私有最终对象锁;
公共服务器线程(对象锁){
this.lock=锁;
}
公共无效标志(){
已同步(锁定){
System.out.println(“等待前”);
试一试{
lock.wait();
System.out.println(“收到通知后”);
}捕获(中断异常例外){
System.out.println(“线程中断”);
}
}
}
公共空间{
已同步(锁定){
System.out.println(“通知所有人之前”);
lock.notifyAll();
System.out.println(“通知所有方法调用之后”);
}
}
公开募捐{
while(true){
System.out.println(“In-serverthread”);
notifyClients();
已同步(锁定){
试一试{
锁。等待(5000);
}捕获(中断异常例外){
}
}
}
}
}
}
我有一个ServerThread变量,并在initialize方法中启动该线程

然而,当我在线程变量上调用flag时,我的整个程序都在等待,而不仅仅是线程。我怎样才能解决这个问题

  • wait()
    只有当另一个线程在调用该对象的同一个对象上调用
    时,才能重新获得锁定。

  • 现在,根据上述声明,我将努力纠正您的问题

    • 首先,在类作用域中创建
      对象锁=新对象()
      ,以便其他线程可以看到它。

    • wait()和notify()
      必须在同步块中,因此将您的
      与要释放其锁的对象一起放入同步块中。

      示例:

      synchronized(lock) {
         lock.notify();
      }
      
  • wait()
    只有当另一个线程在调用该对象的同一个对象上调用
    时,才能重新获得锁定。

  • 现在,根据上述声明,我将努力纠正您的问题

    • 首先,在类作用域中创建
      对象锁=新对象()
      ,以便其他线程可以看到它。

    • wait()和notify()