1.多线程的常用方法
Thread提供了很多与线程操作相关的方法
方法:
public void run(): 线程的任务方法
public void start(): 启动线程
public String getName(): 获取当前线程的名称,线程名称默认是Thread-索引
public void setName(String name): 为线程设置名称
public static Thread currentThread(): 获取当前执行的线程对象
public static void sleep(long time): 让当前执行的线程休眠多少毫秒后,在继续执行
public final void join()。。。: 让当前调用这个方法的线程先执行完。
piblic static yied(): 让出CPU执行权,其他线程执行
常见构造器:
public Thread(String name):可以为当前线程指定名称
public Thread(Runnable target):封装Runnable对象为线程对象
public Thread(Runnable target,String name):封装Runnable对象为线程对象并指定线程名称
2.线程安全问题
线程安全问题指的是:
多个线程同时操作同一个共享资源的时候,可能会出现业务安全问题。(同一个对象中的成员变量)
锁对象随便选择一个唯一的对象不行,会影响到其他无关线程的执行。
锁对象的使用规范:
- 建议使用共享资源作为锁对象,对于实例方法建议使用this作为对象。
- 对于静态方法建议使用字节码(类名.class)对象作为锁对象。
synchronized(同步锁)
同步方法,和同步代码块的线程等待位置不同。
java的线程调用是抢占式调用
Lock比synchronized更灵活
tryLock():尝试是否能获取锁对象,如果获得,就进入执行
如果不能,去执行其他代码,不会死等
Lock是java(内存)层面的锁:通过判断一个变量(0,1)值看是否上锁
synchronized:通过系统,进入阻塞状态,锁被释放,还需要系统将其唤醒。(两次)
jdk6之后synchronized升级了:
偏向锁:
是同步方法,只有一条线程执行时,线程偏向第一个获得锁对象的线程,
下次再进入同步时,无需获得和释放锁对象。
如果有其他线程竞争锁资源,锁会自动升级成轻量级锁
轻量级锁:
当线程竞争不大的时候,没有获得锁对象的线程,会自适应自旋(循环)
如果还是等不到锁对象,则自动升级为重量级锁
重量级锁:
通过系统,进入阻塞状态,锁被释放,还需要系统将其唤醒。
(上面锁升级过程,整个过程不可逆)
lock:
公平锁:新线程会排队,排在阻塞队列的其他线程任务后面等待
非公平锁:新线程会插队,不会进入阻塞队列,而是同阻塞队列中出现的线程任务一同竞争锁资源。
乐观锁:(不加锁)判断旧值和新值(数据库加修改数据,版本号或最后修改时间)
有ABA问题 100->101->100,这是后就不能比旧值,比版本号或时间(这两个一旦被记录就不能改回去)。
悲观锁:直接加锁
3.线程通信
当多个线程共同操作共享的资源时,线程间通过某种方式互相告知自己的状态,以相互协调,避免无效的资源争夺。
生产者消费者模型:
生产者线程负责生产数据
消费者线程负责消费生产者生产的数据。
注意生产者生产完数据应该等待自己,通知消费者消费;消费者消费完数据也应该等待自己,再通知生产者生产!如下:
public class Demo03 {
public static void main(String[] args) {
//创建包子对象
BaoZi bz = new BaoZi();
BaoZiPu bzp = new BaoZiPu(bz);//通过构造方法传对象
bzp.setName("灌汤煎包");
bzp.start();
ChiHuo chiHuo = new ChiHuo(bz);
chiHuo.setName("lisa");
chiHuo.start();
}
}
class BaoZi{
private String xian;
private boolean flag;
public String getXian() {
return xian;
}
public void setXian(String xian) {
this.xian = xian;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public BaoZi() {
}
public BaoZi(String xian, boolean flag) {
this.xian = xian;
this.flag = flag;
}
}
class ChiHuo extends Thread{
private BaoZi bz;
public ChiHuo(BaoZi bz){this.bz = bz;}
public void run(){
while (true){
synchronized (bz){
//没有包子
if (bz.isFlag()==false){
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//有包子,就吃
System.out.println(getName()+"正在吃"+bz.getXian()+"的包子");
bz.setFlag(false);//吃完
//唤醒包子铺线程
bz.notifyAll();//所有
}
}
}
}
class BaoZiPu extends Thread{
private BaoZi bz;
public BaoZiPu(BaoZi bz){
this.bz=bz;
}
public void run(){
while (true){
synchronized (bz){
//没有包子
if (bz.isFlag()==true){
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//没包子,就做
bz.setXian("三鲜");
System.out.println(getName()+"正在制作"+bz.getXian()+"的包子");
bz.setFlag(true);//做完改变包子的状态
//唤醒chihuo线程
bz.notifyAll();//所有
}
}
}
}
4.线程池
线程池是一个可以复用线程的技术。
不使用线程池的问题:
用户每发起一个请求后台就需要创建一个新的线程来处理。
而创建新线程的开销是很大的,并且请求过多的时候,肯定会产生大量的线程出来,会严重影响系统的性能。
作用:
1.控制线程数量
2.提高用户响应速度
3.降低系统资源消耗(一次性创建,用完不销毁,而是归还到线程池)
ThreadPoolExecutor参数:
int corePoolSize, -- 核心线程数
int maximumPoolSize, -- 最大线程数(正式工+临时工)
long keepAliveTime, --临时线程存活时间
TimeUnit unit, -- 时间单位
BlockingQueue<Runnable> workQueue --阻塞队列,阻塞队列可以存放Integer.MAX_VALUE个线程任务,可能造成内存溢出
ThreadFactory threadFactory, --创建线程的方式
RejectedExecutionHandler handler --拒绝策略
ThreadPoolExecutor.CallerRunsPolicy():绕过线程池,由提交线程任务的线程执行。
t.shtdown()关闭线程池
t.sumbit()提交线程任务
核心线程不够用,阻塞队列满了,才会创建临时线程,当都无法及时处理才会执行拒绝策略(main求出了1-600的和是:179700 :main线程执行)
JDK 提供的线程池:
newScheduledThreadPool
延迟执行线程池
让线程任务可以延迟执行,还可以循环执行
也是相当于无边界
newCachedThreadPool
无边界线程池
无法做到对线程数量可控
newFixedThreadPool
有边界线程池
指定线程数量
阻塞队列可以存放Integer.MAX_VALUE个线程任务,可能造成内存溢出
newSingleThreadExecutor
单例线程池
用于执行需要有序执行的线程任务
阻塞队列可以存放Integer.MAX_VALUE个线程任务,可能造成内存溢出
5.线程状态
NEW
创建线程对象时的状态
RUNNABLE
就绪状态
有锁,但是等待CPU执行权
BLOCKING
锁阻塞状态
有CPU执行权,但是没有锁对象
WAITING
无限等待状态
线程调用wait()方法
只有其它线程调用notify()方法才能将其唤醒
唤醒,无锁
锁阻塞状态
唤醒,有锁
就绪状态
TIMED_WAITING
计时等待
线程调用sleep()和wait(time)方法
时间到了自动醒来
有锁
就绪状态
无锁
锁阻塞状态
TERMINATED
死亡状态
run()方法执行完毕
stop()停止线程
标签:对象,void,BaoZi,线程,day12,javaSE,多线程,public,bz
From: https://www.cnblogs.com/wjqblog/p/17232946.html