线程概念 每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。线程是程序中一个单一的顺序控制流程.在单个程序中同时运行多个线程完成不同的工作,称为多线程。一个进程可以产生多个线程,多线程机制使程序运行效率变得更高。进程是指在系统中正在运行的一个应用程序,线程是比进程更小的执行单位 线程的实现方式 测试全班IP是否通,来演示多线程的好处,示例:
public class PingIPDemo {
/**
* pingIp的方法
* @param ipAddr
/
public static void pingIp(String ipAddr){
try {
//Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接,执行命令,把结果放入Process中
Process process = Runtime.getRuntime().exec("ping "+ipAddr);
//使用BufferedReader里面的readLine()方法获取运行时信息
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line=null;
//循环读取结果
while((line=bufferedReader.readLine())!=null){
System.out.println(line);
//如果包含TTL说明ping通
if(line.contains(“TTL”)){
System.out.println(“ping tong”);
return;
}
}
System.out.println(“bu tong”);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
//循环测试班级IP是否通
for(int i=1;i<=3;i++){
pingIp(“192.168.1.”+i);
}
}
}继承thread类实现多线程
public class PingIPExtendThread extends Thread {
private String ip;
/*
* 带参构造
* @param ip
*/
public PingIPExtendThread(String ip){
this.ip=ip;
}
@Override
public void run() {
// TODO Auto-generated method stub
PingIPDemo.pingIp(ip);
}
}public class TestPingIP {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
for(int i=1;i<=3;i++){
//继承Thread后
PingIPExtendThread pingIPExtendThread=new PingIPExtendThread("192.168.1."+i);
//启动线程
pingIPExtendThread.start();
}
}}实现Runnable接口演示多线程
public class PingIPImplementsRunnable implements Runnable {
private String ip;
public PingIPImplementsRunnable(String ip) {
this.ip=ip;
}
@Override
public void run() {
// TODO Auto-generated method stub
PingIPDemo.pingIp(ip);
}}
public class TestPingIP {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/*for(int i=1;i<=3;i++){
//继承Thread后
PingIPExtendThread pingIPExtendThread=new PingIPExtendThread("192.168.1."+i);
//启动线程
pingIPExtendThread.start();
}*/
for(int i=1;i<=3;i++){
//继承Thread后
PingIPImplementsRunnable pingIPImplementsRunnable=new PingIPImplementsRunnable("192.168.1."+i);
//启动线程
new Thread(pingIPImplementsRunnable).start();
}
}}继承thread类和实现runnable接口有什么区别 模拟卖票系统演示区别:继承Thread类受单继承影响,不适合多个线程共享资源
/**
*@className:SaleTicketExtendThread.java
*@discription:
*@createTime:2025-7-8下午5:10:40
*@author:zz
*/
public class SaleTicketExtendThread extends Thread {}实现runnable,主要测试方法不同,实现接口,启动线程时可以两个
/**
*@className:SaleTicketImplementsRunnable.java
*@discription:
*@createTime:2025-7-8下午5:18:41
*@author:zz
*/
public class SaleTicketImplementsRunnable implements Runnable {private int ticket=5;
Object o=new Object();
@Override
public void run() {
// TODO Auto-generated method stub
while(ticket>0){
System.out.println(Thread.currentThread().getName()+"卖票,剩余"+ticket--+"张!");
}
}
public static void main(String[] args) {
SaleTicketImplementsRunnable saleTicketImplementsRunnable =new SaleTicketImplementsRunnable();
new Thread(saleTicketImplementsRunnable,"张三").start();
new Thread(saleTicketImplementsRunnable,"李四").start();
}}线程的状态 五种状态: 新建(程序还没有开始运行线程中的代码) 就绪(当start()方法返回后,线程就处于就绪状态,处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间) 运行(线程获得CPU时间后,它才进入运行状态,真正开始执行run()) 阻塞(等待wait、带超时的等待sleep) 终止(死亡,正常退出或者异常终止)
s(1) 匿名线程类
/**
• @className:AnonymousInternalClass.java
• @discription:
• @createTime:2025-7-8下午10:31:44
• @author:zz
*/
public class AnonymousInternalClass {
public static void main(String[] args) {
// 匿名内部类1
new Thread() {
public void run() {
System.out.println(“我没有名称!!!”);
}
}.start();
// 匿名内部类2
new Thread(new Runnable() {
public void run() {
System.out.println(“我也没有名称!!!”);
}
}).start();
}
}(2) Sleep和wait的区别 讲区别之前,需要先讲解同步锁 synchronized 可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。修改卖票代码,让方法同步,保证卖票不错!
/**
*@className:SaleTicketImplementsRunnable.java
*@discription:
*@createTime:2025-7-8下午5:18:41
*@author:zz
*/
public class SaleTicketImplementsRunnable implements Runnable {private int ticket=5;
@Override
public void run() {
// TODO Auto-generated method stub
while(ticket>0){
synchronized (this) {
System.out.println(Thread.currentThread().getName()+"卖票,剩余"+ticket--+"张!");
}
}
}
public static void main(String[] args) {
SaleTicketImplementsRunnable saleTicketImplementsRunnable =new SaleTicketImplementsRunnable();
new Thread(saleTicketImplementsRunnable,"张三").start();
new Thread(saleTicketImplementsRunnable,"李四").start();
}}1,Sleep方法是在Thread类里面,wait在Object类里面 2,Sleep方法可以不在同步块里面运行,wait不行 3,Wait方法阻塞时,需要唤醒notify操作,释放了锁 4,Sleep放阻塞时,不放锁,wait 方法释放锁,只有当其他线程调用notify方法时,重新获取锁
package com.2025.multithread.demo;
/**
*@className:ThreadStatusDemo.java
*@discription:
*@author:zhz
*@createTime:2025-3-28下午3:56:59
@version:1.0.0
/
public class ThreadStatusDemo {
static Object o = new Object();
static Object o1 = new Object();
static Runnable runnable1 =new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (o) {//首先不加同步锁,讲解sleep用法
System.out.println(“qy76开班”);
try {
//sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过后,cpu才会回到这个线程上继续往下执行
Thread.sleep(10000);
//如果在非同步控制方法里调用notify wait方法,程序能通过编译,但运行的时候,将得到IllegalMonitorStateException异常
//wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法
//notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放。如果notify方法后面的代码还有很多,需要这些代码执行完后才会释放锁
o.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(“qy76毕业”);
}
}
};
static Runnable runnable2 =new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (o) {
System.out.println(“qy80开班”);
try {
Thread.sleep(1000);
o.notify();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(“qy80毕业”);
}
}
};
/
* @param args
/
public static void main(String[] args) {
// TODO Auto-generated method stub
new Thread(runnable1).start();
new Thread(runnable2).start();
}
}(3) 同步块(保证线程正在运行的代码不被其他线程运行)
package com.2025.multithread.demo;
/
*@className:ThreadStatusDemo.java
*@discription:
*@author:zhz
*@createTime:2025-3-28下午3:56:59
@version:1.0.0
/
public class ThreadStatusDemo {
static Object o = new Object();
static Object o1 = new Object();
static Runnable runnable1 =new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (o) {
System.out.println(“qy76开班”);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(“qy76毕业”);
}
}
};
static Runnable runnable2 =new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (o) {
System.out.println(“qy80开班”);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(“qy80毕业”);
}
}
};
/
* @param args
/
public static void main(String[] args) {
// TODO Auto-generated method stub
new Thread(runnable1).start();
new Thread(runnable2).start();
}
}线程的死锁 线程死锁原理:一个线程拥有A锁想得到B锁,另一个线程拥有B锁想得到A锁 使用父亲和儿子的例子演示死锁
/
*@className:Father.java
*@discription:
*@createTime:2025-7-8下午5:57:37
*@author:zz
*/
public class Father {/**
* 说
*/
public void say(){
System.out.println("给我成绩单,我就给你买玩具!");
}
/**
* 得到玩具
*/
public void get(){
System.out.println("得到成绩单!");
}}
/**
*@className:Chirdren.java
@discription:
@createTime:2025-7-8下午5:59:12
@author:zz
/
public class Chirdren {
/
* 说
/
public void say(){
System.out.println(“给我玩具,我就给你成绩单!”);
}
/
* 得到
/
public void get(){
System.out.println(“得到玩具!”);
}
}
package com.2025.multithread.demo;
/
*@className:DeadLockDemo.java
*@discription:
*@author:zhz
*@createTime:2025-3-28下午4:38:41
*@version:1.0.0
**/
public class DeadLockDemo implements Runnable {
static Father father =new Father();
static Chirdren chirdren =new Chirdren();
private boolean isFather=true;
@Override
public void run() {
// TODO Auto-generated method stub
if(isFather){
//拥有父亲锁
synchronized (father) {
father.say();
try {
//睡觉
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//睡醒后要孩子锁,但是没有丢掉父亲锁
synchronized (chirdren) {
father.get();
}
}
}else{
//拥有孩子锁
synchronized (chirdren) {
chirdren.say();
try {
//睡觉
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//睡醒后向要父亲锁,单是没有丢掉孩子锁
synchronized (father){
chirdren.get();
}
}
}
}
public static void main(String[] args) {
DeadLockDemo deadLockDemo1 = new DeadLockDemo();
deadLockDemo1.isFather=true;
DeadLockDemo deadLockDemo2 = new DeadLockDemo();
deadLockDemo2.isFather=false;
new Thread(DeadLockDemo1).start();
new Thread(DeadLockDemo2).start();
}
}