多线程
什么是多线程:
多任务多条路径多个顺序流同时执行就是多线程
多线程的优点:
提高效率,同时执行
多线程的缺点:
复杂
多线程的创建方式:
-
继承Thread类,重写run()方法,run方法中定义多线程的线程体
/** * 线程创建方式 * @author zhuch * */ public class ThreadTest extends Thread{ @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println("犯困"); } } public static void main(String[] args) throws InterruptedException { //创建 ThreadTest t=new ThreadTest(); //开启 t.start(); // TODO Auto-generated method stub for (int i = 0; i < 5; i++) { System.out.println("瞌睡"); Thread.sleep(100); } } }
-
实现Runnable接口,重写run()方法
推荐:
- 避免单继承的局限性
- 实现资源共享
/** * 线程创建方式2 * @author zhuch * */ public class RunnableTest implements Runnable{ @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 5; i++) { System.out.println("梦想"); } } public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub Thread t=new Thread(new RunnableTest()); t.start(); for (int i = 0; i < 5; i++) { System.out.println("远方"); Thread.sleep(10); } } }
-
实现Callable接口,重写call方法
优点:
- 可以抛出异常
- 接收返回值
缺点:使用麻烦
线程安全:
- 多线程同时操作同一份资源才有可能会出现线程不安全的问题,需要控制安全
同步锁:
synchronized
-
为了让线程排队执行{}中的代码
-
同步块 synchronized(锁的内容){同步的代码范围}
-
锁的内容: this 类.class 资源(成员变量)
-
类.class 相当于把这个类,类的所有内容锁住了,类的所有对象都锁住
-
this 当前调用成员方法的对象,相当于把这个对象的所有资源都锁住了,可以只锁资源
-
资源: 成员变量,一定要是自定义的引用数据类型的对象
-
锁的范围:{}->中代码的范围
-
注意:
- 锁的范围太大,效率低
- 锁的范围太小,锁不住
- 锁不变的内容
/** * 多线程打印12A23B45C67D...直到字母打印完结束 * @author zhuch * */ public class Test { public static void main(String[] args) { //创建对象 PrintTest pr=new PrintTest(); //开启线程 new Thread(new Number(pr)).start(); new Thread(new CharTest(pr)).start(); } } //行为 class PrintTest{ //成员变量 boolean flag=false; int num=1; char num1='A'; //打印数字(同步块) public synchronized void number() { if(flag==true) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else { try { Thread.sleep(200); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } for(int i=0;i<2;i++) { if(num==53) { return; } System.out.print(num++); } flag=true; this.notify(); } } //打印字母(同步块) public synchronized void charTest() { if(flag==false) { try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else { try { Thread.sleep(200); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.print((char)(num1++)); flag=false; this.notify(); } } } //数字类实现Runnable接口重写run方法 class Number implements Runnable{ PrintTest pr=null; public Number(PrintTest pr) { super(); this.pr = pr; } @Override public void run() { // TODO Auto-generated method stub while(true) { pr.number(); } } } //字母类实现Runnable接口重写run方法 class CharTest implements Runnable{ PrintTest pr=null; public CharTest(PrintTest pr) { super(); this.pr = pr; } @Override public void run() { // TODO Auto-generated method stub while(true) { pr.charTest(); } } }
public class SynchronizedTest implements Runnable{ Ticket ticket=new Ticket(); public static void main(String[] args) { // TODO Auto-generated method stub SynchronizedTest syn=new SynchronizedTest(); new Thread(syn,"A").start(); new Thread(syn,"B").start(); new Thread(syn,"C").start(); } @Override public void run() { // TODO Auto-generated method stub while(true) { synchronized(this) { if(ticket.num<=0) { break; } try { Thread.sleep(2); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在购买第"+ticket.num-- +"张票"); } } } } class Ticket{ int num=100; }
线程状态:
-
新生状态:new创建一个线程的时候
-
就绪状态:start(),线程会进入就绪队列,等待cpu的调度
-
运行状态:cpu调用分配时间片给线程,线程就会运行
-
阻塞状态:sleep()…
-
终止状态:线程结束了
-
一个线程一旦就如到阻塞状态,阻塞解除之后,不会马上恢复到运行,会恢复到就绪状态,再次等待cpu的调度
-
一个线程一旦进入终止状态,再也不会恢复
-
如何一个线程进入就绪状态:
- 1.start()
- 2.阻塞解除
- 3.线程切换,被切换的线程会恢复就绪状态
- 4.yield() 礼让线程
-
进入阻塞状态的方式:
-
1.sleep
-
2.wait
-
3.join
-
-
如何控制一个线程终止:
- 1.stop…不推荐
- 2.通过表示判断
- 3.正常执行结束
-
sleep(): 线程睡眠
- 1)模拟网络延迟
- 2)放大问题的可能性
- 让出cpu的资源,不会让出对象的锁(保证资源睡觉),指定休息多少毫秒
public class StateTest implements Runnable{
public static void main(String[] args) {
// TODO Auto-generated method stub
StateTest sta=new StateTest();
new Thread(sta,"A").start();
new Thread(sta,"B").start();
}
@Override
public void run() {
// TODO Auto-generated method stub
Thread t=new Thread(()-> {
for (int i = 0; i < 20; i++) {
System.out.println("插队");
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t.start();
try {
t.join();//方法插队
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"开始执行");
Thread.yield();//礼让线程
System.out.println(Thread.currentThread().getName()+"结束执行");
}
}
Thread中 getState() 获取某个线程的状态
线程优先级:
-
提高先执行的概率
- getPriority() 返回该线程的优先级
- setPriority(int newPriority)改变这个线程的优先级
- 1~10 1最小 10最大 默认是5
public class StateDemo02 {
public static void main(String[] args) {
Thread th=new Thread(()->{
for(int i=0;i<=10;i++){
if(i==5){
try {
Thread.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
th.setPriority(10);
System.out.println(th.getPriority());
System.out.println("th线程状态"+th.getState());
th.start();
while(true){
Thread.State state=th.getState();
System.out.println(state);
if(state ==Thread.State.TERMINATED){
break;
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}