等待唤醒机制

  通过等待唤醒机制使各个线程能有效的利用资源。

等待唤醒机制所涉及到的方法:

   wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。

  notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。

  notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。

  所谓唤醒的意思就是让 线程池中的线程具备执行资格。

  必须注意的是:这些方法都是在 同步中才有效;

      同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪  个锁上的线程。而锁又可以是任意对象。能被任意对象调用的方法一定定义在Object类中。

例子:

代码如下:

模拟资源类:

  1. package com.oracle.Resourse;
  2.  
  3. public class Resourse {
  4. public String name;
  5. public String sex;
  6. public boolean flag = false;
  7.  
  8. }

输入线程任务类:

  1. package com.oracle.Resourse;
  2.  
  3. public class InputR implements Runnable{
  4. private int i=0;
  5. private Resourse r=new Resourse();
  6.  
  7. public InputR(Resourse r){
  8. this.r=r;
  9. }
  10. public void run() {
  11. while(true){
  12. synchronized (r){
  13. if(r.flag){
  14.  
  15. try {
  16. r.wait();
  17. } catch (InterruptedException e) {
  18. // TODO Auto-generated catch block
  19. e.printStackTrace();
  20. }
  21. }
  22. if(i%2==0){
  23. r.name="张三";
  24. r.sex="男";
  25. }else{
  26. r.name="LISI";
  27. r.sex="NV";
  28. }
  29. r.flag=true;
  30. r.notify();
  31. }
  32. i++;
  33. }
  34. }
  35.  
  36. }

输出线程任务类:

  1. package com.oracle.Resourse;
  2.  
  3. public class OutputR implements Runnable{
  4.  
  5. private Resourse r=new Resourse();
  6. public OutputR(Resourse r){
  7. this.r=r;
  8.  
  9. }
  10. public void run() {
  11. while(true){
  12. synchronized (r){
  13. if(r.flag==false){
  14. try {
  15. r.wait();
  16. } catch (InterruptedException e) {
  17. // TODO Auto-generated catch block
  18. e.printStackTrace();
  19. }
  20. }
  21. System.out.println(r.name+"..."+r.sex);
  22. r.flag=false;
  23. r.notify();
  24.  
  25. }
  26. }
  27.  
  28. }
  29.  
  30. }

测试类:

  1. package com.oracle.Resourse;
  2.  
  3. public class TEST {
  4.  
  5. public static void main(String[] args) {
  6. Resourse r=new Resourse();
  7. InputR in=new InputR(r);
  8. OutputR out=new OutputR(r) ;
  9. Thread t1=new Thread(in);
  10. Thread t2=new Thread(out);
  11. t1.start();
  12. t2.start();
  13.  
  14. }
  15.  
  16. }

结果如下:

InetAddress类

InetAdderss类,该类用于封装一个IP地址,并提供了一系列与IP地址相关的方法

例子:

  1. public class Example01 {
  2. public static void main(String[] args) throws Exception {
  3. InetAddress local = InetAddress.getLocalHost();
  4. InetAddress remote = InetAddress.getByName("www.oracle.cn");
  5. System.out.println("本机的IP地址:" + local.getHostAddress());
  6. System.out.println("oracle的IP地址:" + remote.getHostAddress());
  7. System.out.println("oracle的主机名为:" + remote.getHostName());
  8. }
  9. }

UDP是一种面向无连接的协议,因此,在通信时发送端和接收端不用建立连接。

DatagramPacket类

  该类的实例对象就相当于一个集装箱,用于封装UDP通信中发送或者接收的数据。

构造方法

 

发送端一定要明确指出数据的目的地(ip地址和端口号),而接收端不需要明确知道数据的来源,只需要接收到数据即可。

DatagramPacket类中的常用方法

DatagramSocket类

  DatagramSocket类的作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包

构造方法:

  该构造方法用于创建发送端的DatagramSocket对象,在创建DatagramSocket对象时,并没有指定端口号,此时,系统会分配一个没有被其它网络程序所使用的端口号。

  该构造方法既可用于创建接收端的DatagramSocket对象,又可以创建发送端的DatagramSocket对象,在创建接收端的DatagramSocket对象时,必须要指定一个端口号,这样就可以监听指定的端口。

常用方法:

例子:

UDP完成数据的发送:

  1. package com.oracle.UdpTcp;
  2.  
  3. import java.io.IOException;
  4. import java.net.DatagramPacket;
  5. import java.net.DatagramSocket;
  6. import java.net.InetAddress;
  7. import java.util.Scanner;
  8.  
  9. public class UDPSend {
  10. public static void main(String[] args) throws IOException {
  11. Scanner sc=new Scanner(System.in );
  12. //InetAddress类调用getbyName方法返回一个本类对象
  13. InetAddress i=InetAddress.getByName("192.168.1.171");
  14. //创建DatagramSocket对象,
  15. DatagramSocket ds = new DatagramSocket();
  16. while(true){
  17.  
  18. //构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
  19.  
  20. //定义字节数组来接收发送端的内容
  21. String mes=sc.next();
  22. byte[] bytes=mes.getBytes();
  23. //装包
  24. DatagramPacket dp = new DatagramPacket(bytes, bytes.length, i, 6666);
  25. ds.send(dp);
  26. }
  27.  
  28. }
  29.  
  30. }

UDP完成数据的接收:

  1. package com.oracle.UdpTcp;
  2.  
  3. import java.io.IOException;
  4. import java.net.DatagramPacket;
  5. import java.net.DatagramSocket;
  6.  
  7. public class UdpS {
  8. public static void main(String[] args) throws IOException {
  9. //1,创建DatagramSocket对象,并指定端口号
  10. DatagramSocket ds = new DatagramSocket(8888);
  11. //创建接收数据的字节数组
  12. byte[] bytes =new byte[1024];
  13. //创建接收数据包
  14. while(true){
  15. DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
  16. //接收
  17. ds.receive(dp);
  18. //获取数据
  19. String ip=dp.getAddress().getHostAddress();//获取IP地址
  20. int port=dp.getPort();//获取端口号
  21. int length = dp.getLength();//获取多少条数据
  22. System.out.println(ip+"..."+port+"发送的内容为"+new String(bytes,0,length));
  23. }
  24.  
  25. // ds.close();
  26. }
  27. }

TCP通信

  在JDK中提供了两个类用于实现TCP程序,一个是ServerSocket类,用于表示服务器端,一个是Socket类,用于表示客户端。

  通信时,首先创建代表服务器端的ServerSocket对象,该对象相当于开启一个服务,并等待客户端的连接,然后创建代表客户端的Socket对象向服务器端发出连接请求,服务器端响应请求,两者建立连接开始通信。

ServerSocket类

构造方法

  使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上(参数port就是端口号)。

ServerSocket的常用方法:

  ServerSocket对象负责监听某台计算机的某个端口号,在创建ServerSocket对象后,需要继续调用该对象的accept()方法,接收来自客户端的请求。当执行了accept()方法之后,服务器端程序会发生阻塞,直到客户端发出连接请求,accept()方法才会返回一个Scoket对象用于和客户端实现通信,程序才能继续向下执行。

Socket类

构造方法

常用方法;

方法声明

功能描述

int getPort()

该方法返回一个int类型对象,该对象是Socket对象与服务器端连接的端口号

InetAddress getLocalAddress()

该方法用于获取Socket对象绑定的本地IP地址,并将IP地址封装成InetAddress类型的对象返回

void close()

该方法用于关闭Socket连接,结束本次通信。在关闭socket之前,应将与socket相关的所有的输入/输出流全部关闭,这是因为一个良好的程序应该在执行完毕时释放所有的资源

InputStream getInputStream()

该方法返回一个InputStream类型的输入流对象,如果该对象是由服务器端的Socket返回,就用于读取客户端发送的数据,反之,用于读取服务器端发送的数据

OutputStream getOutputStream()

该方法返回一个OutputStream类型的输出流对象,如果该对象是由服务器端的Socket返回,就用于向客户端发送数据,反之,用于向服务器端发送数据

例子:

客户端程序:

  1. package com.oracle.Tcp;
  2.  
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.OutputStream;
  6. import java.net.Socket;
  7.  
  8. public class TCPK {
  9. public static void main(String[] args) throws IOException {
  10. //创建socket对象,连接服务器
  11. Socket s=new Socket ("127.0.0.1",7777 );
  12. //通过客户端套接字对象Socket对象中的获取字节输出流的方法
  13. OutputStream out=s.getOutputStream();
  14. //将数据写向服务器
  15. out.write("服务器你好".getBytes());
  16. //接收服务器端的回复
  17. InputStream in=s.getInputStream();
  18. byte[] bytes=new byte[1024];
  19. int len=in.read(bytes);
  20. System.out.println(new String(bytes,0,len));
  21. s.close();
  22.  
  23. }
  24.  
  25. }

服务器端程序:

  1. package com.oracle.Tcp;
  2.  
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.OutputStream;
  6. import java.net.ServerSocket;
  7. import java.net.Socket;
  8.  
  9. public class TCPS {
  10.  
  11. public static void main(String[] args) throws IOException {
  12. //创建服务器套接字
  13. ServerSocket ss=new ServerSocket(7777);
  14. //调用ACCEPT方法与客户端创建链接
  15. Socket s=ss.accept();
  16. InputStream in=s.getInputStream();
  17. byte[] bytes=new byte[1024];
  18. int len=in.read(bytes);
  19. System.out.println(new String(bytes,0,len));
  20. //服务器端给回复
  21. OutputStream out=s.getOutputStream();
  22. out.write("收到".getBytes());
  23.  
  24. }
  25.  
  26. }

文件上传案例

首先编写服务器端程序,用来接收图片。

  1. package com.oracle.TCPS;
  2.  
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.io.InputStream;
  8. import java.io.OutputStream;
  9. import java.net.ServerSocket;
  10. import java.net.Socket;
  11. import java.util.Random;
  12.  
  13. public class TCPS {
  14.  
  15. public static void main(String[] args) throws IOException {
  16. ServerSocket server=new ServerSocket(7500);//明确端口号
  17. Socket socket=server.accept();
  18. //读取文件,明确数据源
  19. InputStream in=socket.getInputStream();
  20. //明确目的地
  21. File file=new File("e:\\JPG");
  22. //判断文件是否存在
  23. if(!file.exists()){
  24. file.mkdirs();//没有则创建文件夹
  25. }
  26. //域名+毫秒值+6位随机数
  27. // 随机数
  28. String num="";
  29. for(int i=0;i<6;i++){
  30. num+=new Random().nextInt(10);
  31. }
  32. String filename="oracle"+System.currentTimeMillis()+num+".jpg";
  33. FileOutputStream fos=new FileOutputStream(file+File.separator+filename);
  34. //复制‘
  35. int len=0;
  36. byte[] bytes=new byte[1024];
  37. while((len=in.read(bytes))!=-1){
  38. fos.write(bytes,0,len);//往服务器端写
  39. }
  40. //回复客户端
  41. OutputStream out=socket.getOutputStream();
  42. out.write("上传成功".getBytes());
  43. fos.close();
  44. server.close();
  45.  
  46. }
  47.  
  48. }

客户端程序:

  1. package com.oracle.TCPS;
  2.  
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.io.OutputStream;
  7. import java.net.Socket;
  8. import java.net.UnknownHostException;
  9.  
  10. public class TCPK {
  11.  
  12. public static void main(String[] args) throws UnknownHostException, IOException {
  13. //创建socket对象,连接服务器
  14. Socket socket=new Socket ("127.0.0.1",7500 );
  15. //获取Socket流中的输出流,功能:用来把数据写到服务器
  16. OutputStream out=socket.getOutputStream();
  17. //从文件读到客户端
  18. FileInputStream fis=new FileInputStream("E:\\QQwenjian\\1972680739\\FileRecv\\0601.jpg");
  19. //定义字节数组接收文件
  20. byte[] bytes=new byte[1024];
  21.  
  22. int len=0;
  23. while((len=fis.read(bytes))!=-1){
  24. out.write(bytes,0,len);
  25. }
  26. //客户端发送数据完毕,结束Socket输出流的写入操作,告知服务器端,不再读了
  27. socket.shutdownOutput();
  28.  
  29. //接收服务器端的回复
  30. InputStream in=socket.getInputStream();
  31. len=in.read(bytes);
  32. System.out.println(new String(bytes,0,len));//将字节数组内容转成字符串打印出来
  33. //释放资源
  34. fis.close();
  35. socket.close();
  36. }
  37.  
  38. }

多文件上传案例

只需将服务器端代码封装改一下:

  1. package com.oracle.TCPS;
  2.  
  3. import java.io.File;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.OutputStream;
  8. import java.net.InetAddress;
  9. import java.net.Socket;
  10. import java.util.Random;
  11.  
  12. public class UpLoad implements Runnable{
  13.  
  14. private Socket socket;
  15. public UpLoad(Socket socket){
  16. this.socket=socket;
  17. }
  18. public void run() {
  19. FileOutputStream fos=null;
  20.  
  21. try{
  22. //显示哪个客户端Socket连接上了服务器
  23. InetAddress ipObject = socket.getInetAddress();//得到IP地址对象
  24. String ip = ipObject.getHostAddress(); //得到IP地址字符串
  25. System.out.println("小样,抓到你了,连接我!!" + "IP:" + ip);
  26.  
  27. //读取文件,明确数据源
  28. InputStream in=socket.getInputStream();
  29. //明确目的地
  30. File file=new File("e:\\JPG");
  31. //判断文件是否存在
  32. if(!file.exists()){
  33. file.mkdirs();//没有则创建文件夹
  34. }
  35. //域名+毫秒值+6位随机数
  36. String filename="oracle"+System.currentTimeMillis()+new Random().nextInt(6)+".jpg";
  37. fos=new FileOutputStream(file+File.separator+filename);
  38. //复制,把Socket输入流中的数据,写入目的地的字节输出流中‘
  39. int len=0;
  40. byte[] bytes=new byte[1024];
  41. while((len=in.read(bytes))!=-1){
  42. fos.write(bytes,0,len);//往服务器端写
  43. }
  44. //回复客户端
  45. OutputStream out=socket.getOutputStream();
  46. out.write("上传成功".getBytes());
  47. }catch (IOException ex){
  48. ex.printStackTrace();
  49. }finally{
  50. try {
  51. fos.close();
  52. } catch (IOException e) {
  53. // TODO Auto-generated catch block
  54. e.printStackTrace();
  55. }
  56. }
  57.  
  58. }
  59.  
  60. }

测试类:

  1. package com.oracle.TCPS;
  2.  
  3. import java.io.IOException;
  4. import java.net.ServerSocket;
  5. import java.net.Socket;
  6.  
  7. public class Demo {
  8.  
  9. public static void main(String[] args) throws IOException {
  10. ServerSocket server=new ServerSocket(7500);//明确端口号
  11. while(true){
  12. Socket socket=server.accept();
  13. new Thread(new UpLoad(socket)).start();//匿名内部类
  14.  
  15. }
  16. }
  17.  
  18. }

等待唤醒机制,UDP通信和TCP通信的更多相关文章

  1. java之等待唤醒机制(线程之间的通信)

    线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同.比如:线程A用来生成包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的动作,一个是生产,一个是消 ...

  2. 等待唤醒机制----线程池----lambda表达式

    1.等待唤醒机制 1.1线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同. 比如:线程A用来生成包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的 ...

  3. java基础知识回顾之java Thread类学习(七)--java多线程通信等待唤醒机制(wait和notify,notifyAll)

    1.wait和notify,notifyAll: wait和notify,notifyAll是Object类方法,因为等待和唤醒必须是同一个锁,不可以对不同锁中的线程进行唤醒,而锁可以是任意对象,所以 ...

  4. 多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)

    一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name   sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. ...

  5. Java 之 线程 —线程通信( 等待唤醒机制)

    一.线程间通信 概念:多个线程在处理同一资源,但是处理的动作(线程的任务)却不相同. 例如: 线程 A 用来生成包子的,线程 B 用来吃包子的,包子可以理解为同一资源,线程 A 与线程 B 处理的动作 ...

  6. java基础知识回顾之java Thread类学习(八)--java多线程通信等待唤醒机制经典应用(生产者消费者)

     *java多线程--等待唤醒机制:经典的体现"生产者和消费者模型 *对于此模型,应该明确以下几点: *1.生产者仅仅在仓库未满的时候生产,仓库满了则停止生产. *2.消费者仅仅在有产品的时 ...

  7. java-等待唤醒机制(线程中的通信)-线程池

    为什么需要线程间的通信 多个线程并发执行时,在默认情况下CPU时随机切换线程的,当我们需要多个线程共同完成一件任务,并且 希望他们有规律的执行,那么多线程之间需要一些协调通信,以此来帮我们达到多线程共 ...

  8. java多线程(死锁,lock接口,等待唤醒机制)

    一.Lock接口 常用方法 Lock提供了一个更加面对对象的锁,在该锁中提供了更多的操作锁的功能. 使用Lock接口,以及其中的lock()方法和unlock()方法替代同步,对电影院卖票案例中Tic ...

  9. Java多线程02(线程安全、线程同步、等待唤醒机制)

    Java多线程2(线程安全.线程同步.等待唤醒机制.单例设计模式) 1.线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量 ...

随机推荐

  1. vue proxyTable 接口跨域请求调试(五)

    在不同域之间访问是比较常见,在本地调试访问远程服务器....这就是有域问题. VUE解决通过proxyTable: 在 config/index.js 配置文件中 dev: { env: requir ...

  2. C# 通过 Hessian服务调用java

    1.下载Hessiancsharp.dll 2.新建一个c#窗体程序,然后在添加一个类库 3.添加一个接口类,接口中的方法名和参数与java中的服务方法名和参数保持一致 public partial ...

  3. kmspico

    # process | 在这儿找到了原作者的地址 http://blog.nsfocus.net/kmspico/ | 下面是原作者地址 https://forums.mydigitallife.ne ...

  4. Ancient Messages UVA - 1103

    题目链接:https://vjudge.net/problem/UVA-1103 题目大意:每组数据包含H行W列的字符矩阵(H<=200,W<=50) 每个字符为为16进制  你需要把它转 ...

  5. 使用summernote编辑器上传图片,重写onImageUpload

    JS部分:$('.summernote').summernote({ height: 200,//高度 tabsize: 2,//页面上的summernote编辑框的个数 lang: 'zh-CN', ...

  6. 性能测试工具Jmeter07-Jmeter性能测试实战

    测试需求:测试20个用户访问www.baozhenart.com在负载达到30QPS时的平均响应时间 QPS:Query Per Second每秒查询率.是一台查询服务器每秒能够处理的查询次数.在因特 ...

  7. vue-cli生成的重要代码详解

    安装好vue-cli之后,我们可以在package.json中看到下面所示: { // 项目名称 "name": "myvue", // 项目版本 " ...

  8. Emacs学习笔记2

    emacs的启动初始化 需要有一个~/.emacs文件, 这个和vim一样 emacs中的查找与替换 递增查找 C-s, 在minibuffer中输入即可, 在一次C-s会跳转到下一个 两次C-g取消 ...

  9. 自定义HandlerMethodArgumentResolver参数解析器和源码分析

    在初学springmvc框架时,我就一直有一个疑问,为什么controller方法上竟然可以放这么多的参数,而且都能得到想要的对象,比如HttpServletRequest或HttpServletRe ...

  10. as3.0 动态文本属性大全

    var my_fmt = new TextFormat();//常用样式 my_fmt.align = "center"; my_fmt.blockIndent = 50; //区 ...