「JAVA线程广播」Java广播

博主:adminadmin 2023-01-20 18:57:08 359

今天给各位分享JAVA线程广播的知识,其中也会对Java广播进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

java的socket编程中的线程问题!

没用多线程的时候服务端只能和一个客户端完成通信后再和另一建立连接,而不能同时。

java socket,我有客户端和服务器的代码,帮我添加广播和能多人会话,加分!!代码如下

根据你的改了个!不好意思,其中读写的思路稍微有点不同!不过可以做参考!

Server端代码:

import java.net.*;

import java.io.*;

import java.util.*;

public class TestServer {

ServerSocket s = null;

boolean started = false;//用来监听服务器是否启动!

ListServerReaderWriter clients = new ArrayListServerReaderWriter();//用来存放启动的客服端

public static void main(String[] args) {

new TestServer().start();

}

public void start() {

try {

s = new ServerSocket(5050);

started = true;

} catch(SocketException e) {

System.out.println("5050端口正在使用中!!!请关掉相关程序并重新运行服务器!");

System.exit(0);

} catch (IOException e) {

e.printStackTrace();

}

int i = 1;

try {

while(started) {

Socket ss = s.accept();

ServerReaderWriter c = new ServerReaderWriter(ss);//建立客服端

System.out.println("第" + i + "个客服端启动!");

++i;

new Thread(c).start();//启动线程

clients.add(c);

}

} catch (EOFException e) {

System.out.println("客服端被关闭!");

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

s.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

class ServerReaderWriter implements Runnable { //建议使用Runnable避免你重写run方法麻烦!

private Socket s;

private DataInputStream dis = null;//注意赋值,养成好习惯!

private DataOutputStream dos = null;

private boolean bConnected = false;//用于调用连接成功后的run方法

public ServerReaderWriter(Socket s) {

this.s = s;

try {

dis = new DataInputStream(s.getInputStream());

dos = new DataOutputStream(s.getOutputStream());

bConnected = true;

} catch (IOException e) {

e.printStackTrace();

}

}

public void send(String str) {

try {

dos.writeUTF(str);

} catch (IOException e) {

clients.remove(this);

System.out.println("有客户退出!");

}

}

public void run() {

try {

while (bConnected) {

String input = dis.readUTF();

System.out.println(input);

for(int i=0; iclients.size(); ++i) {

ServerReaderWriter c = clients.get(i);

c.send(input);

}

}

} catch(SocketException e) {

System.out.println("一个客服端已关闭,请勿再像他发送信息!");

} catch (EOFException e) {

System.out.println("谢谢使用!");

}catch (IOException e) {

e.printStackTrace();

} finally {

try {

if (dis != null) {

dis.close();

}

if (dos != null) {

dos.close();

}

if (s != null) {

s.close();

s = null;

}

//clients.clear();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

}

}

Client端代码:

import java.io.*;

import java.net.*;

import java.awt.*;

import java.awt.event.*;

public class TestClient extends Frame { //用到Frame生产界面比较直观

Socket s = null;

DataOutputStream dos = null;

DataInputStream dis = null;

private boolean bConnected = false;

TextField tfText = new TextField();

TextArea taContent = new TextArea();

Thread tRecv = new Thread(new ClientReaderWriter());

public static void main(String[] args){

new TestClient().launchFrame();

}

public void launchFrame() {

this.setSize(300, 300); //设置客服端窗口格式

this.setLocation(400, 300);

add(tfText, BorderLayout.SOUTH);

add(taContent, BorderLayout.NORTH);

this.pack();

this.addWindowListener(new WindowAdapter() { //监听窗口关闭事件

public void windowClosing(WindowEvent arg0) {

disconnect();

System.exit(0);

}

});

tfText.addActionListener(new TFListener());

setVisible(true);

connect();

tRecv.start();

}

public void connect() {

try {

s = new Socket("127.0.0.1", 5050); //依据自己的服务器,我这里用的localhost

dos = new DataOutputStream(s.getOutputStream());

dis = new DataInputStream(s.getInputStream());

System.out.println("连接服务器!");

bConnected = true;

} catch(ConnectException e) {

System.out.println("请检查服务器是否启动!");

try {

Thread.sleep(1000);

} catch (InterruptedException e1) {

e1.printStackTrace();

}

System.exit(0);

}

catch (UnknownHostException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

public void disconnect() {

try {

dos.close();

dis.close();

s.close();

} catch (IOException e) {

e.printStackTrace();

}

}

private class TFListener implements ActionListener {

public void actionPerformed(ActionEvent e) {

String str = tfText.getText().trim();

tfText.setText("");

try {

dos.writeUTF(str);

if(str.equals("bye")){

System.exit(0);

}

dos.flush();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

class ClientReaderWriter implements Runnable {

public void run() {

try {

while(bConnected) {

String input = dis.readUTF();

taContent.setText(taContent.getText() + input +'\n');

}

} catch (SocketException e) {

System.out.println("轻轻的我走了!Bye-bye!");

} catch (EOFException e) {

System.out.println("我断网了,再见!");

}

catch (IOException e) {

e.printStackTrace();

}

}

}

}

关于Java多线程的(高手请帮忙)

package First;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.PrintStream;

import com.sun.media.sound.Toolkit;

public class test {

static int num = 0;

public static void main(String[] args) {

System.out.println("now:" + num );

new test().start();

}

class Thd implements Runnable{//创建线程

public void run() {

num ++;

System.out.println( num + "\n");

}

}

class Thd1 implements Runnable{//创建线程

public void run() {

num --;

System.out.println( num + "\n");

}

}

public void start() {

for ( int i = 0;i 2; i ++){

Thd th1 = new Thd();

new Thread(th1).start();//线程启动

}

for ( int i = 0;i 2; i ++){

Thd1 th = new Thd1();

new Thread(th).start();//线程启动

}

}

}

java的线程之间如何进行消息传递

原生Java线程之间只能通过共享内存(同一个虚拟机内)来通信。当然你可以通过自己实现,使得线程看起来可以通过消息通信。比如Scala的Actor,可以通过消息传递,但Actor本身和线程是有很大不同,不过看起来具备了一些线程功能 。

如何用Java回调和线程实现异步调用

软件模块之间的调用关系可以分为两大类:即同步调用和异步调用。在同步调用中,一段代码(主调方)调用另一段代码(被调方),主调方必须等待这段代码执行完成返回结果后,才能继续往下执行,所以,同步调用是一种阻塞式调用,主调方代码一直阻塞等待直到被调方返回为止。同步调用相对比较直观,也是大部分编程语言直接支持的一种调用方式。但是,同步调用在处理比较耗时的情况下会严重影响程序性能,影响人机交互的瞬时反应。例如,某个程序需要访问数据库获取大量数据,然后根据这些数据进行一系列处理,将处理结果显示在程序主窗口。由于数据库访问和大量数据的处理都是耗时的工作,在这个工作完成之前,处理结果迟迟不能显示,用户点击鼠标也不会立即得到响应,让用户感到整个程序显得很沉重。面对这样一些需要比较长时间才能完成的应用场景,我们需要采用一种非阻塞式调用方式,即异步调用方式。在异步调用中,主调方调用被调方后,不等待对方返回结果就继续执行后续代码,被调方执行完毕后,通过某种手段通知调用方:结果已经出来,请酌情处理。我们可以对上面的例子改用异步调用将问题轻松化解:把整个耗时的工作放进一个单独的线程,由主调方启动此线程后继续执行后续代码,线程在背后悄悄地处理费时的工作,当工作完成,采用回调的方式通知主调方工作完成,主调方将结果显示在主窗口。经过这样的处理,主界面继续进行自己的工作而不必死等,就不会造成界面响应迟钝。

在实现异步调用机制时,除了线程之外,还要用到回调。回调是一种双向调用,也就是,被调方在被调用时也会调用主调方的代码。在异步调用中,被调方需要在工作完成时通知主调方,即调用主调方的接口,这一机制通过回调实现。回调和异步调用的关系非常紧密,回调是异步调用的基础[1]。

本文理论联系实际,首先阐述如何使用Java实现回调机制,然后进一步阐述使用Java回调和线程实现异步调用,最后,阐述在异步调用中如何处理超时问题。

1 Java回调机制的实现方法

实现Java回调,需要做如下三件事情:

(1)定义一个回调接口CallbackInterface

接口中声明回调方法handle,如图1所示,回调方法就是一个普通的方法,接收一个消息字符串或者一个封装了数据的事件。

(2)定义一个类实现回调接口

这个类其实就是消息接收者和处理者,也就是调用方,回调方法是消息发生时实际处理消息的方法,此处简化为一条打印语句。

(3)定义消息通知者

消息通知者也就是被调用方必须具备两种能力,第一,它必须知道谁是消息接收者,第二,当消息发生时,它能够回调这些接收者的回调方法。为了获得这两种能力,消息通知者首先必须提供一个注册方法register, 通过注册的方式来注册多个对此消息或事件感兴趣的对象。然后提供一个消息通知方法notifyMessage,在这个方法中调用所有消息接收者的回调方法。具体代码如图3所示。

比如用一个可变数组List用于保存消息接收者,注册的过程实际上是将消息接收者添加到这个数组,以备在需要通知消息的时候调用这些消息接收者的回调方法。

使用Java回调和线程实现异步调用

线程是一个独立的执行流,其本质是程序中一段并发执行的代码。在异步调用机制中引入线程,在线程中完成耗时的工作,其目的是让调用方的主线程继续执行后续代码而不需要等待被调方的结果返回。由于不需要等待,这样我们就等于同时做了两件事情,而这两件事情分别是在不同的执行流中执行,主调者在当前的主线程中执行,被调者在另外一个线程中执行,因此提高了程序的效率,避免了界面的响应迟钝。当被调者执行完成后,仍然采用回调通知主调者。

例如 LongTimeWorker是一个用于完成耗时工作的线程,同时又是消息通知者。其耗时工作在run方法中完成,另外提供一个注册方法register, 和一个消息通知方法notifyMessage,在run方法的最后,即耗时工作完成以后,调用notifyMessage将消息广播出去。

3 异步调用中超时问题的处理

异步调用通常都要加入超时机制,因为我们总是希望在一个指定的时间范围内返回一个结果,即使没有得到结果也该有个超时通知。这时我们需要使用“限时线程回调方式”,它在原有线程回调的基础上加上一个计时器Timer以计算消耗的时间,如果时间期限到了任务还没有执行完成即中断线程,并将超时消息广播出去。LongTimeWorker类需要修改部分的代码如图8和图9所示。

首先LongTimeWorker线程类增加了一个构造方法,其参数是超时时间timeout,构造方法的主要任务是创建一个定时器,每秒钟计时一次,若超时时间到则终止本线程,并广播超时消息。LongTimeWorker线程类的第二个改变发生在其run方法中,线程一启动立即开始计时,完成工作后停止计时,并广播消息。

4 结束语

异步调用是一种非阻塞式调用方式,用于在处理比较耗时的任务时保证程序性能不受到影响。实现异步调用的关键在于要解决三个技术难题,它们分别是程序阻塞问题、异步消息的传递问题和超时问题。本文介绍的方法采用并发线程、回调机制和计时器使上述问题得到了圆满解决。

JAVA线程广播的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于Java广播、JAVA线程广播的信息别忘了在本站进行查找喔。