什么是线程?
进程中的一个执行流程
什么是多线程?
进程中有两个或两个以上这样的执行流程
线程的五种状态:
1.新建(New):创建一个线程对象:Thread t = new Thread();
2.就绪(Runnable):等待CPU的调用执行
3.运行(Running):被CPU调用执行
4.阻塞(Blocked):运行者的线程由于某种原因暂停了CPU的调用执行
1)sleep
2)同步
3)wait
5.死亡(Dead):线程终止
启动一个java程序至少会启动几个线程?(2个:主线程和垃圾回收线程)
java中实现线程的方式:
1.继承Thread类
2.实现Runnable接口
区别:
slepp(),wait(),join()区别:
sleep(): 放弃CPU的执行权,但是不会放弃锁,线程A处于sleep()那么,线程A就处于阻塞装填,当参数的时间超时了,那么会回到就绪状态等待CPU调用执行
wait():放弃CPU的执行权,但是会放弃锁
join():当在主线程中调用子线程的join(),那么主线程处于阻塞状态,等待子线程执行完再恢复执行
线程中断:
-
1.继承Thread可以继承到Thread的所有方法
-
2.实现接口只有一个run()方法,更有利于资源共享
-
线程让步:
-
理论上:线程A让步给同等优先级的线程B,级别比他高的线程B
-
-
-
线程的同步
-
同步代码块
-
同步方法:锁的都是对象(synchronized当两个线程同时调用一个方法的对象的时候需要加一个锁)
-
-
加锁:
-
当线程A执行到了同步代码块或同步的方法代码的时候,需要获得此对象的同步锁,获得成功,那么其他线程B进入锁定池中处于锁定状态
-
-
释放锁:
-
当线程A正常执行完同步代码块或同步方法中的代码时
-
当代码块或方法中出现没有解决的Error或Exception时
-
当代码块或方法中出现return,break时
-
wait
-
【实例】
wait():线程让步【十分重要】
package day8_21;
/**wait()*/
class Qingfeng {
private int count;
boolean tag = false;
synchronized public void put(int count) {
if (tag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.count=count;
System.out.println("生产了:"+this.count);
tag=true;
notify();
}
synchronized public void get() {
if (tag==false) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("卖了:"+this.count);
tag=false;
notify();
}
}
class Producer implements Runnable{
Qingfeng qingfeng;
Producer(Qingfeng qingfeng){
this.qingfeng=qingfeng;
}
@Override
public void run() {
for(int i=1;i<=5;i++) {
qingfeng.put(i);
}
}
}
class Consumer implements Runnable{
Qingfeng qingfeng;
Consumer(Qingfeng qingfeng){
this.qingfeng=qingfeng;
}
@Override
public void run() {
for(int i=1;i<=5;i++) {
qingfeng.get();
}
}
}
public class TestShop {
public static void main(String[] args) {
Qingfeng qingfeng = new Qingfeng();
Producer p = new Producer(qingfeng);
Consumer c = new Consumer(qingfeng);
Thread t1 = new Thread(p);
t1.start();
Thread t2 = new Thread(c);
t2.start();
}
}
线程让步:join()和isAlive()
package day8_20;
class ThreadDemo implements Runnable{
@Override
public void run() {
for (int i = 1; i <= 3; i++) {
// System.out.println("hello");
System.out.println(Thread.currentThread().getName()+"玩游戏");
}
}
}
public class TestSubThread3 {
public static void main(String[] args) {
ThreadDemo demo = new ThreadDemo();
Thread zs = new Thread(demo,"张三");
zs.start();
Thread ls = new Thread(demo,"李四");
ls.start();
//等待
/*try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
//少等一会儿isAlive()当前线程是否处于运行状态 true
/*if(zs.isAlive()||ls.isAlive()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}*/
try {
zs.join();
ls.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main结束了");
}
}
synchronized:锁方法或代码块(添加方法实现共用一个对象)
package day8_20;
class Bank implements Runnable{
private int money;
//锁的是对象 this
synchronized public void setMoney() {
this.money+=100;
System.out.println("余额:"+Thread.currentThread().getName()+":"+money);
}
@Override
public void run() {
for(int i=1;i<=3;i++) {
// synchronized (this) {
setMoney();
// }
}
}
}
public class TestSubThread5 {
public static void main(String[] args) {
Bank bank = new Bank();
Thread t1 = new Thread(bank,"zs");
Thread t2 = new Thread(bank,"ls");
t1.start();
t2.start();
}
}
加锁和释放锁(lock与unlock)
package day8_21;
/**加锁(休眠等待)*/
import java.util.concurrent.locks.ReentrantLock;
class Ticket implements Runnable{
private int ticket=20;
ReentrantLock lock =new ReentrantLock();
public void show(){
//加锁
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+":"+ticket);
ticket-=1;
return;
} catch (Exception e) {
e.printStackTrace();
}finally {
//释放锁
lock.unlock();}
}
@Override
public void run() {
for(int i=1;i<=10;i++){
// synchronized (this) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
show();
// }
}
}
}
public class TestTicket {
public static void main(String[] args) {
Ticket tic= new Ticket();
Thread t1 = new Thread(tic,"窗口1");
Thread t2 = new Thread(tic,"窗口2");
t1.start();
t2.start();
}
}
死锁(仅做了解)
package day8_21;
//死锁
class Zhangsan{
public void say() {
System.out.println("你给我书,我就给你画");
}
public void get() {
System.out.println("张三获得了书");
}
}
class Lisi{
public void say() {
System.out.println("你给我画,我就给你书");
}
public void get() {
System.out.println("李四获得了画");
}
}
class ThreadDemo implements Runnable{
private static Zhangsan zhangsan = new Zhangsan();
private static Lisi lisi = new Lisi();
public boolean tag = false;
public void run() {
if(tag) {
synchronized (zhangsan) {
zhangsan.say();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lisi) {
zhangsan.get();
}
}
}else {
synchronized (lisi) {
lisi.say();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (zhangsan) {
lisi.get();
}
}
}
}
}
public class TestDead {
public static void main(String[] args) {
ThreadDemo demo1 = new ThreadDemo();
demo1.tag = true;
ThreadDemo demo2 = new ThreadDemo();
demo2.tag = false;
Thread t1 = new Thread(demo1);
Thread t2 = new Thread(demo2);
t1.start();
t2.start();
}
}