package com.bjsxt.homework.Thread; public class JoinThread { public static void main(String[] args) { System.out.println("main线程开始"); Thread t1 = new Thread(new A()); t1.start(); //new B().start(); for(int i =0;i<10;i++){ System.out.println(Thread.currentThread().getName()+"正在运行"+i); //i=3时,main被挂起,直到A执行完。 if (i == 3) { try { t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } System.out.println("main线程结束"); } } class A implements Runnable{ Thread t = new B(); @Override public void run() { t.run(); for(int i =0;i<10;i++){ System.out.println(Thread.currentThread().getName()+"正在运行"+i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //i=5时,A被挂起,直到B执行完。 if(i==5){ try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } } }} } class B extends Thread{ @Override public void run() { for(int i =0;i<10;i++){ System.out.println(Thread.currentThread().getName()+"正在运行!!!"+i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
com.bjsxt.homework.Thread; JoinThread { main(String[] args) { System..println(); Thread t1 = Thread(A()); t1.start(); (i =;i<;i++){ System..println(Thread.().getName()++i); (i == ) { { t1.join(); } (InterruptedException e) { e.printStackTrace(); } } } System..println(); } } A Runnable{ Thread = B(); run() { .run(); (i =;i<;i++){ System..println(Thread.().getName()++i); { Thread.(); } (InterruptedException e) { e.printStackTrace(); } (i==){ { .join(); } (InterruptedException e) { e.printStackTrace(); } } }} } B Thread{ run() { (i =;i<;i++){ System..println(Thread.().getName()++i); { Thread.(); } (InterruptedException e) { e.printStackTrace(); } } } }
代码:
运行结果:main线程开始main正在运行0main正在运行1main正在运行2main正在运行3Thread-1正在运行!!!0Thread-1正在运行!!!1Thread-1正在运行!!!2Thread-1正在运行!!!3Thread-1正在运行!!!4Thread-1正在运行!!!5Thread-1正在运行!!!6Thread-1正在运行!!!7Thread-1正在运行!!!8Thread-1正在运行!!!9Thread-1正在运行0Thread-1正在运行1Thread-1正在运行2Thread-1正在运行3Thread-1正在运行4Thread-1正在运行5Thread-1正在运行6Thread-1正在运行7Thread-1正在运行8Thread-1正在运行9main正在运行4main正在运行5main正在运行6main正在运行7main正在运行8main正在运行9main线程结束Process finished with exit code 0
请问为什么线程中不能创建线程呢???只有一个Thread1
/** * 定义馒头类 */ class mantou2{ private int id ; public int getId() { return id; } public void setId(int id) { this.id = id; } public mantou2(int id) { this.id = id; } } /** * 定义缓冲区 */ class buffer{ private mantou2[] mt = new mantou2[10]; private int index ; /** * 放馒头 */ public synchronized void push(mantou2 mantou2){ while (this.index == this.mt.length){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } notify(); this.mt[index] = mantou2 ; index++ ; } /** * 取馒头 */ public synchronized mantou2 pop(){ while (this.index == 0){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } notify(); this.index--; return this.mt[index] ; } } /** * 取馒头线程 */ class qumantou extends Thread{ buffer buffer = new buffer(); public qumantou(com.itbz.buffer buffer) { this.buffer = buffer; } @Override public void run() { for (int i = 0; i < 10;i++){ buffer.pop() ; System.out.println("取馒头" + i); } } } /** * 放馒头线程 */ class cunmantou extends Thread{ buffer buffer = new buffer(); public cunmantou(com.itbz.buffer buffer) { this.buffer = buffer; } @Override public void run() { for (int i = 0; i < 10;i++){ System.out.println("存馒头" + i); mantou2 mantou2 = new mantou2(i); buffer.push(mantou2); } } } public class ProductThread2 { public static void main(String[] args) { buffer buffer = new buffer(); cunmantou cunmantou = new cunmantou(buffer); qumantou qumantou = new qumantou(buffer); cunmantou.start(); qumantou.start(); } }
问题 在主方法中声明两个存取馒头的时候,要对存取馒头两个类进行增加有参构造方法而不能使用默认无参构造方法才能正常,如果使用无参构造方法时,程序会阻塞?为什么?这块不太理解
这里是什么问题我看了几遍没有发现问题,和老师写的应该一样的这个导入的包为什么会变成灰色
请问老师,key.hashCode()这里的意思就是取哈希值的低16位吗
老师,这个自动拆箱、装箱中的编译器,是指jdk吗?jdk不是集成开发工具吗?或者说是IEDA?
老师好,请问容器一般是在什么情况下使用的
老师,我不太明白,
finally{ try{ if(bis != null){ bis.close(); } } }
当中,为什么bis != null 时才可以关闭这个流?不等于空不应该是说明这个流里有东西,所以更不应该关闭才对吗
为什么有的类中private定义的成员变量有其get方法,有的没有?
class Manager{ private String name; public Manager(String name){ this.name=name; } public String getName(){ return this.name; } class SaleMan{ private String name; public SaleMan(String name){ this.name=name; }
老师,是不是因为private限定了该属性只能被本类访问,所以在反射的时候不能通过安全检查
老师,一对多聊天服务中,我的客户端不是每次都能返回消息。
下面的是服务端的代码
package com.bjsxt.ls.网络编程.TCP.一对多聊天服务器; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; //创建服务端接收消息的线程 class ChatReceive extends Thread{ private Socket ss; public ChatReceive(Socket n){ this.ss=n; } @Override public void run() { this.receive1(); } //创建接收消息的线程 public void receive1(){ BufferedReader br =null; try { br = new BufferedReader(new InputStreamReader(this.ss.getInputStream())); while (true){ String jieshou = br.readLine(); synchronized ("同步锁") { //要让发送消息和接收消息的线程处于同步状态,需要在两个线程上加上同一个名字的对象锁 ChatServer.BUF = jieshou; //将接收到的消息保存到缓存区 "同步锁".notify(); //当消息存到缓存区之后,唤醒发送消息线程,可以发送消息了 } } } catch (IOException e) { e.printStackTrace(); }finally { if (br != null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (this.ss != null){ try { ss.close(); } catch (IOException e) { e.printStackTrace(); } } } } } //创建服务端发送消息的线程类 class ChatSend extends Thread{ private Socket ss; public ChatSend(Socket n){ this.ss=n; } @Override public void run() { this.send1(); } //创建发送消息的方法 public void send1(){ PrintWriter pw = null ; try { pw = new PrintWriter(this.ss.getOutputStream()); while (true) { synchronized ("同步锁") { //要让发送消息和接收消息的线程处于同步状态,需要在两个线程上加上同一个名字的对象锁 "同步锁".wait(); //发送消息的线程应先处于等待状态 pw.println(ChatServer.BUF); //将消息从缓存区取出,因为BUF是static的,直接用类名就能调用 pw.flush(); } } } catch (Exception e) { e.printStackTrace(); }finally { if (pw != null){ pw.close(); } if (this.ss != null){ try { this.ss.close(); } catch (IOException e) { e.printStackTrace(); } } } } } //主线程用于启动服务端,客户端可以使用之前的“点对点优化”中的GoodP2P public class ChatServer { //定义一个字符串类型的缓存区 public static String BUF; public static void main(String[] args) { System.out.println("正在启动服务器....."); System.out.println("<HappyDay>聊天室启动"); ServerSocket serverSocket = null; try { serverSocket =new ServerSocket(332); while (true){ Socket sk =serverSocket.accept(); //将启动服务端放在循环中,因为每次发送或接收消息都需要启动服务端 System.out.println("已经连接到IP地址为["+ InetAddress.getLocalHost() +"]的主机。"); new ChatReceive(sk).start(); //启动线程 new ChatSend(sk).start(); } } catch (IOException e) { e.printStackTrace(); }finally { if(serverSocket!=null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
这个是用的优化的点对点聊天作为客户端的代码
package com.bjsxt.ls.网络编程.TCP.点对点优化; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; //创建发送消息线程 class send1 extends Thread{ private Socket socket =null; private Scanner scanner =null; public send1(Socket s1,Scanner s2){ this.socket =s1; this.scanner=s2; } //创建发送消息的方法 public void sengmessage(){ PrintWriter pw =null; try{ pw =new PrintWriter(socket.getOutputStream()); scanner = new Scanner(System.in); while (true){ String say =scanner.nextLine(); pw.println(say); pw.flush(); } }catch (Exception e){ e.printStackTrace(); }finally { if (pw != null){ pw.close(); } if (scanner != null){ scanner.close(); } if (socket != null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public void run() { this.sengmessage(); } } //创建接收消息的线程 class receive extends Thread{ private Socket socket =null; public receive(Socket x){ this.socket = x; } public void receivemessage(){ BufferedReader br= null; try { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); while (true){ String rs = br.readLine(); System.out.println("收到的消息是:"+rs); } } catch (IOException e) { e.printStackTrace(); }finally { if (br != null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket!= null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public void run() { this.receivemessage(); } } public class GoodP2P { public static void main(String[] args) { Scanner scanner = null; ServerSocket serverSocket = null; Socket socket = null; scanner =new Scanner(System.in); System.out.println("请输入:server,<port> 或者:" + "<ip>,<port>"); String str = scanner.nextLine(); String arr[] =str.split(",");//以逗号为分割点存入数组 //判断当输入的server时,启动服务端 if ("server".equals(arr[0])){ System.out.println("TCP点对点通信,正在启动服务端,连接端口号["+arr[1]+"]"); try { serverSocket =new ServerSocket(Integer.parseInt(arr[1]));//将字符串强转为整型 socket = serverSocket.accept(); } catch (IOException e) { e.printStackTrace(); } System.out.println("连接成功!"); } //当输入的不是server时,即进入客户端 else { try { socket = new Socket(arr[0],Integer.parseInt(arr[1])); System.out.println("连接成功!"); } catch (IOException e) { e.printStackTrace(); } } //启动发送消息的线程 new send1(socket,scanner).start(); new receive(socket).start(); if (serverSocket != null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
下面的运行的截图:
服务端测试
客户端1
客户端2
客户端3
老师,既然控制台上输入了server,那么就是进入了启动服务端的线程。那客户端又是怎么启动的呢?客户端不是放在else中了嘛,选了server那么else里面的内容就不会执行了呀,那客户端也不会启动了呀。我有点不理解这里,请老师解答一下。
我这个问题是在哪?
/** * 账户类 */ class Account{ private String accountNum;//账户 private double balance;//余额 public Account(){ } public Account(String accountNum, double balance) { this.accountNum = accountNum; this.balance = balance; } public String getAccountNum() { return accountNum; } public void setAccountNum(String accountNum) { this.accountNum = accountNum; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } } class DrawMoney extends Thread{ private Account account;//账户对象 private double drawMoney;//取款金额 public DrawMoney(String name,Account account,double drawMoney){ super(name); this.account=account; this.drawMoney=drawMoney; } /** * 取款线程 */ @Override public void run() { if (this.account.getBalance()>=this.drawMoney){ System.out.println(this.getName()+"取钱成功 "+this.drawMoney); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } this.account.setBalance(this.account.getBalance()-this.drawMoney); System.out.println("\t 余额为:"+this.account.getBalance()); }else { System.out.println(this.getName()+"取钱失败"); } } } public class DrawMoneyThread { public static void main(String[] args) { Account account=new Account("1234",1000); new DrawMoney("小王",account,800).start(); new DrawMoney("李梅",account,500).start(); } }
老师,这个线程并发为什么不需要像生产者消费者模型一样,用一个缓冲区来缓存消息呢?
非常抱歉给您带来不好的体验!为了更深入的了解您的学习情况以及遇到的问题,您可以直接拨打投诉热线:
我们将在第一时间处理好您的问题!
关于
课程分类
百战程序员微信公众号
百战程序员微信小程序
©2014-2025百战汇智(北京)科技有限公司 All Rights Reserved 北京亦庄经济开发区科创十四街 赛蒂国际工业园网站维护:百战汇智(北京)科技有限公司 京公网安备 11011402011233号 京ICP备18060230号-3 营业执照 经营许可证:京B2-20212637