创建线程两种方式
A:继承Thread,重写run,代码存放进去,调用start启动线程
B:实现Runnable接口,重写run,代码存放进去,new Thread(Runnable子类对象),调用start启动线程
sleep(long time):Thread类中方法,不释放锁,释放cpu执行权
wait():释放锁,释放cpu执行权
notify():唤醒等待线程,通常唤醒最先等待的线程。
notfiyAll():唤醒所有等待线程。
A:wait和notify,notifyAll,为什么这几个方法需要锁对象去调用?
锁是用来确定哪些同步代码块属于同一个范畴。
同一范畴的wait,只能用该范畴的notify或notifyAll去唤醒。
B:wait和notify,notifyAll为什么定义Object中?
因为这些方法需要锁对象调用,锁对象可以是任意对象。
------------------------
线程池--存放线程的
线程例子:
package com.sxt.thread;
/**
* 需求:
* 100张票4个窗口同时起售
* 4个窗口--4条线程
* 100张票--4条线程,共享数据。
* ---------------------------------------
* 线程的数据安全问题
* 现象:出现数据错乱。0 -1 -2 多个100
* 原因:多条线程 停在了 多条操作共性数据语句中间
* 1.多条线程
* 2.多条“共性数据”语句
* 以上两者同时存在就会出现---数据安全问题
* 解决:
* 保证 线程在执行 多条“共性数据”语句 时,只能进入一条线程。
* 保证 单线程操作 多条“共性数据”语句
*
* 同步机制--同步代码块,所封装的部分,只允许有一条线程进入。
* synchronized(任意对象){//任意对象--监视器/锁/锁旗标
* 2.多条“共性数据”语句
* }
*
*
*/
class Ticket implements Runnable{
Object obj = new Object();
int num = 1000;//100张票,共享数据
@Override
public void run() {
while(true){
synchronized(obj){
if(num>0){
//刻意的让线程在这里停10毫秒
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"::"+num);
num--;
}
}
}
}
}
public class TicketTest2{
public static void main(String[] args) {
Ticket2 ticket = new Ticket2();
//以下四条线程
Thread t1 = new Thread(ticket);
Thread t2 = new Thread(ticket);
Thread t3 = new Thread(ticket);
Thread t4 = new Thread(ticket);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
/**
* 生产者和消费者的问题--等待唤醒机制
*
* 现象1:生产过多或者消费过多。
*
* 原因:生产者线程,生产完商品后,唤醒了本方线程,继续生产商品,导致商品没有被消费,丢失。
* 解决:让每条线程醒来后,第一件事,回头去判断标记。if-->while
* --------------------------------------------------------------
* 现象2:if-->while后,导致所有线程都死翘翘了。出现了死锁现象。
* 原因:让每条线程醒来后,第一件事,回头去判断标记,直接wait了。
* 解决:需要有活着的线程。notifyAll,在本方线程全死掉前,至少保证对面活了。
*/
class Res{
String name;
int count = 0;//计数器
boolean flag = false;
//生产
public synchronized void set(String name){
//
while(flag)
try {this.wait();} catch (Exception e) {}//A(等待)
//B(醒了)
this.name = name+count++; //商品1 商品2 商品3
System.out.println(Thread.currentThread().getName()+
":::生产者:::"+this.name);
flag = true;
this.notifyAll();
}//
//消费
public synchronized void out(){
//
while(!flag)
try {this.wait();} catch (Exception e) {}//C(等待)D(等待)
System.out.println(Thread.currentThread().getName()+"------消费者-------"
+this.name); //商品1
flag = false;
this.notifyAll();
}
}
class In implements Runnable{
Res r;
In(Res r){
this.r = r;
}
@Override
public void run() {
while(true)
r.set("商品");
}
}
class Out implements Runnable{
Res r;
Out(Res r){
this.r = r;
}
@Override
public void run() {
while(true)
r.out();
}
}
public class ThreadTest {
public static void main(String[] args) {
Res r = new Res();
new Thread(new In(r)).start();
new Thread(new In(r)).start();
new Thread(new Out(r)).start();
new Thread(new Out(r)).start();
}
}