多线程
1.线程和进程
进程:进行中的程序,只有程序在运行过程中,才能称之为进程。计算机CPU分配资源的最小单位。
线程:每个进程至少包含一个线程。进程和线程的关系就像车和车轮,线程不是越多越好,要结合实际的硬件条件。(线程是CPU调度和分派的基本单位)
线程执行的基本概念:单核心CPU的情况,线程是轮流交替执行,而且是随机的,每个线程最多执行的时间是20ms,间隔短,所以我们感知不到这个过程,宏观上看就是"同时"执行。
并行和并发:
并发:同时发生,比如你点了两份菜,从饭店老板的角度(宏观)看,你是同时吃完的,但是严格来说,是轮流交替执行的(微观角度).
并行:同时执行,比如你和同桌一人点了一份菜,这才是真正意义的同时执行。
2.创建线程的方式
1.继承Thread类,重写run方法
2.实现Runnable接口,实现run方法
面试题:
调用start方法和run方法的区别?
调用start方法会开启一个新的线程
不能调用run方法,因为不会开启新的线程
/**
* 创建线程方式1 继承Thread类 重写run方法
* 面试题:调用start方法和run方法的区别
* 启动线程调用start方法 会开启一个新的线程
* 不能调用run方法 因为不会开启新的线程
* @author asus
*/
public class Test2 extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 线程执行run方法……");
}
public static void main(String[] args) {
Test2 t2 = new Test2();
t2.setName("线程A");
// t2.start(); // 启动线程 调用start方法 不能调用run方法
t2.run();
}
}
/**
* 创建线程方式2 实现Runnable接口 重写run方法
* @author asus
*/
public class Test3 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "在执行……");
}
public static void main(String[] args) {
Test3 t3 = new Test3();
Thread t1 = new Thread(t3); //这才是线程1;
Thread t2 = new Thread(t3); //这才是线程2;
// Thread t1 = new Thread(t3 , "线程A");
t1.start();
}
}
3.线程的状态
创建--》就绪--》运行--》阻塞--》死亡
/**
* 线程的状态
* @author asus
*/
public class Test4 extends Thread{
@Override
public void run() {
// 运行
// 阻塞 休眠 等待
for (int i = 1; i <= 10; i++) {
System.out.println(Thread.currentThread().getName() + "在执行" + i);
}
}
// 死亡
public static void main(String[] args) {
Test4 t1 = new Test4(); // 创建状态
Test4 t2 = new Test4(); // 创建状态
t1.start(); // 就绪状态
t2.start(); // 就绪状态
}
}
4.线程常用的方法
getName() 获取线程名称
setName() 设置线程名称
getPriority() 获取线程优先级
setPriority() 设置线程优先级
MAX_PRIORITY 最大优先级10
MIN_PRIORITY 最小优先级1
NORM_PRIORITY 默认优先级5
sleep() 休眠方法
join() 线程插队
yield() 线程礼让(并不能保证一定会礼让)
interrupt() 改变当前线程标识,标识此线程可以被中断,不是立即中断
isAlive() 是否存活状态
stop() 中断线程
currentThread() 获取当前线程对象
5.同步关键字
synchronized: 同步
通常用·this
适用场景:
修饰代码块:表示同步代码块
1.同一时刻只能有一个线程访问此同步代码块synchronized(this)
2.但其他线程可以访问没有被修饰的代码。
3.其他被synchronized(this)修饰的代码块同样被锁定
修饰方法:同步方法,同时只能有一个线程访问此方法
•同一时刻只能有一个线程进入synchronized(this)同步代码块
•当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定
•当一个线程访问一个synchronized(this)同步代码块时,其他线程可以访问该资源的非synchronized(this)同步代码
/**
* 买票
* 多个人抢票
* 三个人 10张票
* synchronized 同步
* 适用场景:代码块 方法
* @author asus
*/
public class BuyTicket2 implements Runnable{
private int count = 10;
@Override
public void run() {
while(true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
if(count == 0) {
break;
}
count --; System.out.println(Thread.currentThread().getName() + "抢到了第"+(10 - count)+"张票,还剩余" + count);
}
// 这里的 其他线程也访问
}
}
public static void main(String[] args) {
BuyTicket2 bt = new BuyTicket2();
Thread t1 = new Thread(bt, "赵四");
Thread t2 = new Thread(bt, "广坤");
Thread t3 = new Thread(bt, "大拿");
t1.start();
t2.start();
t3.start();
}
}
/**
* 买票
* 多个人抢票
* 三个人 10张票
* synchronized 同步
* 适用场景:
* 代码块 表示同时只能有一个线程执行当前代码块
* 方法 表示同时只能有一个线程执行当前方法
* 回顾我们之前所学线程安全的类 StringBuffer
* @author asus
*/
public class BuyTicket3 implements Runnable{
private int count = 10;
@Override
public synchronized void run() {
while(true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(count == 0) {
break;
}
count --;
System.out.println(Thread.currentThread().getName() + "抢到了第"+(10 - count)+"张票,还剩余" + count);
}
}
public static void main(String[] args) {
BuyTicket3 bt = new BuyTicket3();
Thread t1 = new Thread(bt, "赵四");
Thread t2 = new Thread(bt, "广坤");
Thread t3 = new Thread(bt, "大拿");
t1.start();
t2.start();
t3.start();
}
}
每日问题
1.线程的状态
2.创建线程的方式 两种方式的区别
3.调用start和调用run方法的区别
4.线程调度的方法
5.进程和线程的区别
6.同步关键字的作用,规则
7.书写同步关键字
8.礼让和插队有什么区别
解答:
1.线程的状态
创建 就绪 运行 阻塞 死亡
2.创建线程的方式 两种方式的区别
继承Thread类 重写run方法 书写简单 适用于单继承
实现Runnable接口 重写run方法 可以实现数据共享 多用组合
少用继承
3.调用start和调用run方法的区别
start方法开启新线程 run方法不不会开启新线程
4.线程调度的方法
sleep 休眠 join 插入
yield 礼让 stop 中断
start 开始
5.进程和线程的区别
进程是cpu最小的分配资源单位 进程可以有多个线程
6.同步关键字的作用,规则
修饰代码块
1.同时只能有一个线程访问此代码块
2.可以访问没有被修饰代码
3.其他被synchronized修饰的代码块同样被锁定 修饰方法 同步方法,同时只能有一个线程访问此方法
7.书写同步关键字
synchronized
8.礼让和插队有什么区别
礼让不一定会礼让 插队是一定会插队