JAVA135-185
- 多线程
- 多线程成员方法
- 线程优先级
- eg,卖票(线程的安全问题)需要解决线程同时抢的问题
- 同步方法
- LOCK锁
- 等待唤醒机制
- 阻塞队列实现等待唤醒机制
- 多线程的六种状态
- 红包
- 抽奖箱抽奖
- 比较
- 线程池
- 最大并行数
- 网络编程
- InetAdress
- 端口号
- 协议
- 练习
- Tcp发送和接收数据
- 三次握手四次挥手
- 多发多收
多线程
多线程的第一种启动方式:
1.自己定义一个类继承Thread
2.重写run方法
3.创建子类的对象,并启动线程
public class Demo {
public static void main(String[] args) {
Mythread t1=new Mythread();
t1.start();//开启线程
}
}
public class Mythread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("HelloWorld");
}
}
}
多线程的第二种启动方式:
1.自己定义一个类实现Runnable接口
2.重写里面的run方法
3.创建自己的类的对象
4.创建一个Thread类的对象,并开启线程
//创建MyRun的对象
/表示多线程要执行的任务
MyRun mr = new MyRun();
//创建线程对象
Thread t1 = new Thread(mr);
/开启线程
t1.start();
public void run(){
//书写线程要执行的代码
for (int i =0;i< 100;i++){
∥获取到当前线程的对象
Thread t = Thread.currentThread();
System.out.println(t.getName() + "Helloworld!");
}
}
多线程的第三种实现方式:
特点:可以获取到多线程运行的结果
1.创建一个柒MyCallable实现callable接口
2.重写ca11~(是有返回值的,表示多线程运行的结果)
3.创建MyCallable的对象(表示多线程要执行的任务)
4.创建FutureTask的对象(作用管理多线程运行的结果)
5.创建Thread类的对象,并启动(表示线程)
//创建MyCallable的对象(表示多线程要执行的任务)
MyCallable mc = new MyCallable();
//创建FutureTask的对象(作用管理多线程运行的结果)
FutureTask<Integer> ft = new FutureTask<>(mc);
//创建线程的对象
Thread t1 = new Thread(ft);
//启动线程
t1.start();
//获取多线程运行的结果
Integer result = ft.get();
System.out.println(result);
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
//求1~100之间的和
int sum = 0;
for (int i = 1;i <= 100; i++){
sum = sum + i;
}
return sum;
}
}
多线程成员方法
返回此线程的名称
String getName()
设置线程的名字(构造方法也可以设置名
void setName(String name)
细节:
1、如果我们没有给线程设置名字,线程也是有默认的名字的
格式:Thread-x(x序号,从e开始的)
2、如果我们要给线程设置名字,可以用set方法进行设置,也可以构造方法设置
获取当前线程的对象
static Thread currentThread()
让线程休眠指定的时间,单位为毫秒
static void sleep(long time)
让线程休眠指定的时间,隐位为毫秒
static void sleep(long time)
细节:
1、哪条线程执行到这个方法,那么哪条线程就会在这里停留对应的时间
2、方法的参数:就表示睡眠的时间,单位毫秒
1秒=1000毫秒
3、当时间到了之后,线程会自动的醒来,继续执行下面的其他代码
线程优先级
eg,卖票(线程的安全问题)需要解决线程同时抢的问题
package com.itheima.thread02;
public class ThreadDemo {
public static void main(String[] args) {
MyThread t1=new MyThread();
MyThread t2=new MyThread();
MyThread t3=new MyThread();
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
package com.itheima.thread02;
public class MyThread extends Thread {
//表示所有
static int ticket = 0;//表示
static Object obj=new Object();
@Override
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (obj){
if (ticket < 100) {
ticket++;
System.out.println(getName() + "正在卖第" + ticket + "票!!");
} else {
break;
}
}
}
}
}
同步方法
package com.itheima.thread02;
public class MyRunnable implements Runnable {
int ticket = 0;
@Override
public void run() {
while (true)
if (extracted()) break;
}
private synchronized boolean extracted() {
synchronized (MyRunnable.class) {
if(ticket==100){
return true;
}else {
ticket++;
System.out.println(Thread.currentThread().getName()+"在卖"+ticket+"票");
}
}
return false;
}
}
package com.itheima.thread02;
public class ThreadDemo {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);
Thread t3 = new Thread(mr);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
LOCK锁
等待唤醒机制
package com.itheima.waitmodify;
public class Cook extends Thread{
@Override
public void run() {
while (true){
synchronized (Desk.lock){
if(Desk.count==0){
break;
}else{
if(Desk.foodFlag==1){
try {
Desk.lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}else{
System.out.println("厨师做了一碗面条");
Desk.foodFlag=1;
Desk.lock.notifyAll();
}
}
}
}
}
}
package com.itheima.waitmodify;
public class Foodile extends Thread {
@Override
public void run() {
/*
1.循环
2.同步代码块
3.判断共享数据是否到了末尾(到了末尾)
4. 判断共享数据是否到了末尾(没有到末尾)
*/
while (true) {
synchronized (Desk.lock) {
if (Desk.count == 0) {
break;
} else {
//先判断桌子上是否有面条,。没有就等待,如果有就开吃
//吃完之后要唤醒厨师继续做,把吃的总数-1 修改桌子的状态
if(Desk.foodFlag==0){
try {
Desk.lock.wait();//让当前线程跟锁绑定
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
Desk.lock.notifyAll();
}else{
System.out.println("吃货正在吃面条还能吃+"+Desk.count+"wan");
Desk.lock.notifyAll();
Desk.count--;
Desk.foodFlag=0;
}
}
}
}
}
}
package com.itheima.waitmodify;
public class Desk {
//作用:控制生产者和消费者的执行
public static int foodFlag=0; //是否有面条,0:有面条 1:无面条
//总个数
public static int count=10;
public static Object lock=new Object();
}
阻塞队列实现等待唤醒机制
多线程的六种状态
红包
package com.itheima.test4cas1;
public class Test {
/*
微信中的抢红包也用到了多线程。
假设:100块,分成了3个包,现在有5个人去抢。
其中,红包是共享数据。
5个人是5条线程。
打印结果如下:
XXX抢到了XXX元
XXX抢到了XXX元
XXX抢到了XXX元
XXX没抢到
XXX没抢到
*/
public static void main(String[] args) {
MyThread t1=new MyThread();
MyThread t2=new MyThread();
MyThread t3=new MyThread();
MyThread t4=new MyThread();
MyThread t5=new MyThread();
t1.setName("xaa1");
t2.setName("xaaQ");
t3.setName("xaa1qweqwe");
t4.setName("xaa1qwes");
t5.setName("xaasadsssssdsadas1");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
package com.itheima.test4cas1;
import java.util.Random;
public class MyThread extends Thread {
static double money = 200;
static int count = 3;
static final double MIN = 0.01;
@Override
public void run() {
//循环
//同步代码块
//判断是否到末尾(到了)
//判断是否到末尾(没到)
//
synchronized (MyThread.class) {
if (count == 0) {//判断是否到末尾(到了)
System.out.println(getName() + "没有抢到红包");
} else {
double prize = 0;
//判断,共享数据是否到了末尾(没有到末尾)
//不能直接随机
if (count == 1) {
prize = money;
//表示此时是最后一个红包
//就无需随机,剩余的所有钱都是中奖金额
} else {
//表示第一次第二次的中奖情况
Random r = new Random();
double bounds = money - (count - 1) * MIN;
prize = r.nextDouble(bounds);
if (prize < MIN) {
prize = MIN;
}
}
money = money - prize;
count--;
System.out.println(getName()+"抢到了红包"+prize);
}
}
}
}
抽奖箱抽奖
有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为{10,5,20,50,100,200,500,800,2,80,300,700};
创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”
随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
每次抽出一个奖项就打印一个(随机)
抽奖箱1又产生了一个10元大奖
抽奖箱1又产生了一个100元大奖
抽奖箱1又产生了一个200元大奖
抽奖箱1又产生了一个800元大奖
抽奖箱2又产生了一个700元大奖
package com.itheima.Test5;
import java.util.ArrayList;
import java.util.Collections;
public class MyThread extends Thread{
ArrayList<Integer> list;
public MyThread(ArrayList<Integer> list) {
this.list = list;
}
@Override
public void run() {
while (true){
synchronized (MyThread.class){
if(list.size()==0){
break;
}
else{
Collections.shuffle(list);
Integer prize = list.remove(0);
System.out.println(getName()+"又产生了一个"+prize+"大奖");
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
package com.itheima.Test5;
import java.util.ArrayList;
import java.util.Collections;
public class Test {
//有一个抽奖池,该抽奖池中存放了奖励的金额,该抽奖池中的奖项为{10,5,20,50,100,200,500,800,2,80,300,700};
//创建两个抽奖箱(线程)设置线程名称分别为“抽奖箱1”,“抽奖箱2”
//随机从抽奖池中获取奖项元素并打印在控制台上,格式如下:
//每次抽出一个奖项就打印一个(随机)
//抽奖箱1又产生了一个10元大奖
//抽奖箱1又产生了一个100元大奖
//抽奖箱1又产生了一个200元大奖
//抽奖箱1又产生了一个800元大奖
//抽奖箱2又产生了一个700元大奖
public static void main(String[] args) {
ArrayList<Integer> list=new ArrayList<>();
Collections.addAll(list ,10,5,20,50,100,200,500,800,2,80,300,700);
MyThread t1=new MyThread(list);
MyThread t2=new MyThread(list);
t1.setName("抽奖箱1");
t2.setName("抽奖箱2");
t2.start();
t1.start();
}
}
比较
package com.itheima.Test5;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Integer> {
ArrayList<Integer> list;
static ArrayList<Integer> list1=new ArrayList<>();
static ArrayList<Integer> list2=new ArrayList<>();
public MyCallable(ArrayList<Integer> list) {
this.list = list;
}
@Override
public Integer call() throws Exception {
ArrayList<Integer> boxlist=new ArrayList<>();
while (true){
synchronized (MyCallable.class){
if(list.size()==0){
System.out.println(Thread.currentThread().getName()+boxlist);
break;
}
else{
Collections.shuffle(list);
Integer prize = list.remove(0);
boxlist.add(prize);
// System.out.println(getName()+"又产生了一个"+prize+"大奖");
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if (boxlist.size()==0){
return null;
}else{return Collections.max(boxlist);}
}
}
线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor
(核心线程数量,最大线程数量,空闲线程最大存活时间,任务队列,创建线程工厂,任务的拒绝策略);
参数一:核心线程数量
不能小于e
不能小于等于0,最大数量>=核心线程数量
不能小于e
参数二:最大线程数
参数三:空闲线程最大存活时间
参数四:时间单位
用TimeUnit指定
不能为nul1
参数五:任务队列
不能为null
不能为nul1
参数六:创建线程工厂
参数七:任务的拒绝策略
最大并行数
网络编程
InetAdress
package com.itheima.MyInetAdressDemo;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class MyInetAdressDemo1 {
public static void main(String[] args) throws UnknownHostException {
/*
static InetAddress getByName(String host) 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
String getHostName() 获取此IP地址的主机名
String getHostAddress() 返回文本显示中的IP地址字符串
*/
InetAddress address = InetAddress.getByName("DESKTOP-4LVLCVP");
System.out.println(address);
String name = address.getHostName();
System.out.println(name);
String ip = address.getHostAddress();
System.out.println(ip);
}
}
端口号
协议
package com.itheima.MyInetAdressDemo;
import java.io.IOException;
import java.net.*;
public class SendMessageDemo {
public static void main(String[] args) throws IOException {
//发送数据
//1.创建DatagramSocket对象(快递公司)
//细节:
//绑定端口:以后我们就是通过这个端口往外发送数据
//空参:所有可用的端口中随机一个进行使用
//有参:指定端口号进行绑定
DatagramSocket ds = new DatagramSocket();
//2.打包数据
String str = "你好威猛啊!!!!";
byte[] bytes = str.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 10086;
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
//3.发送数据
ds.send(dp);
ds.close();
}
}
练习
package com.itheima.UDPTEST;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class SendMessageDemo {
public static void main(String[] args) throws IOException {
//按照下面的要求实现程序
//UDP发送数据:数据来自于键盘录入,直到输入的数据是886,发送数据结束
//UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收
//1.创建对象DatagramSocket
DatagramSocket ds = new DatagramSocket();
//2.打包数据
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入你要说的话");
String str=sc.nextLine();
if("886".equals(str)){
break;
}
byte[] bytes = str.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port =10086;
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
//3发送数据
ds.send(dp);
}
//4.释放资源
ds.close();
}
}
package com.itheima.UDPTEST;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ReceiveMessageDemo {
public static void main(String[] args) throws IOException {
//1.创建对象DatagramSocket的对象
DatagramSocket ds = new DatagramSocket(10086);
//2.接受数据包
byte[] bytes=new byte[1024];
DatagramPacket dp=new DatagramPacket(bytes, bytes.length);
while (true) {
ds.receive(dp);
//3.解析数据包
byte[] data = dp.getData();
int len = dp.getLength();
String ip = dp.getAddress().getHostAddress();
String name = dp.getAddress().getHostName();
//打印数据
System.out.println("ip wei " + ip + ",主机名为" + name + "的人,发送了数据" + new String(data, 0, len));
}
}
}
Tcp发送和接收数据
package com.itheima.a05tcpDemo1;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class Client { public static void main(String[] args) throws IOException {
//TCP协议,发送数据
//1.创建Socket对象
//细节:在创建对象的同时会连接服务端
// 如果连接不上,代码会报错
Socket socket =new Socket("127.0.0.1",10000);
//2.从连接通道中获取输出流
OutputStream os = socket.getOutputStream();
//写出数据
os.write("你好你好".getBytes());
//3.释放资源
os.close();
socket.close();
}
}
package com.itheima.a05tcpDemo1;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
//Tcp协议,接收数据
//1.创建对象SeverSocket
ServerSocket ss = new ServerSocket(10000);
//2.监听客户端链接
Socket socket = ss.accept();
//3.从链接通道中 获取输入流读取数据
InputStream is = socket.getInputStream();
int b;
while ((b=is.read())!=-1){
System.out.println((char) b);
}
}
}
三次握手四次挥手
多发多收
package com.itheima.a07Test1;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
//1.创建对象绑定10000端口
ServerSocket ss=new ServerSocket(10000);
//2.等待客户端链接
Socket socket = ss.accept();
//3.读取数据
InputStreamReader isr=new InputStreamReader(socket.getInputStream());
int b;
while((b= isr.read())!=-1){
System.out.println((char)b);
}
//4.释放资源
socket.close();
ss.close();
}
}
package com.itheima.a07Test1;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws IOException {
//客户端:多次发送数据
//服务器:接受多次数据,并打印
//1.创建Socket对象并链接服务端
Socket socket =new Socket("127.0.0.1",10000);
//2.写数据
Scanner sc = new Scanner(System.in);
String str=sc.nextLine();
System.out.println("请输入您要发送的信息");
OutputStream os=socket.getOutputStream();
os. write(str.getBytes());
//3.释放资源
socket.close();
}
}