目录:
一、线程
进程: 计算机内存中 运行的一个应用程序。
线程: 进程中的一个执行流程。
多线程: 进程中 有两个 或 两个以上这样并发的执行流程。
底层并发的原理: 多个线程 轮询执行。
二、线程状态
线程可以分为五个状态,
创建:Thread t = new Thread()
就绪: Runnable 等待cpu的调用执行;
运行:Running 处于就绪状态的线程 一旦 被 cpu调用执行了,那么处于运行状态;
阻塞:Bloked wait notify() sleep() join() syschronized
死亡:Dead 线程 正常 或 异常结束
三、线程
1.主线程
最先启动的线程。
产生其它 子线程 的线程。
任务 : main()中
2.子线程
多线程的三种实现方式:
1. 继承 Threa 类 重写run方法
private String name;
public SubThread(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void run(){
for (int i = 1; i < 6; i++) {
System.out.println(Thread.currentThread()+":"+i);
}
}
}
public class TestThreads {
public static void main(String[] args) {
// TODO Auto-generated method stub
SubThread subThread = new SubThread("妖君");
// System.out.println(Thread.currentThread());
subThread.start();
2.继承Runnable 接口 实现run方法
@Override
public void run() {
for(int i = 1; i <= 3; i++) {
// 获得当前线程的 名字
System.out.println(Thread.currentThread().getName()+ ":" + i);
}
}
}
public class TestSubThread2 {
public static void main(String[] args) {
// 不是线程类的对象
SubThread2 sub2 = new SubThread2();
// 创建了一个线程类对象
Thread t = new Thread(sub2,"t1");
t.start();
}
3.实现Callable接口 和继承Runnable 一样 不同的是有返回值
@Override
public Integer call() throws Exception {
// TODO Auto-generated method stub
int sum =0;
for (int i = 0; i < 7; i++) {
System.out.println(Thread.currentThread()+":"+i);
sum +=i;
}
return sum;
}
}
public class TestCallable {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// TODO Auto-generated method stub
BB bb = new BB();
FutureTask ft = new FutureTask<Integer>(bb);
Thread t = new Thread(ft,"妖君");
t.start();
System.out.println(ft.get());
Runnable 接口 和 Callable接口的区别:
1.Runnable 是普通接口 Callable是泛型接口
2.Runnable没有返回值 Callable 有返回值
3.Runnable 重写run方法 Callable 重写call()
4。共同点:都可以共享资源
四、线程的优先级
五、方法
1.interrupt()线程中断
sleep()和join()
线程 A 被 线程B中断了,那么线程A进入异常处理。
class SubThread5 implements Runnable{
@Override
public void run() {
for(int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
if(i == 3) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "进入异常处理");
}
}
}
}
}
public class TestSubThread5 {
public static void main(String[] args) {
SubThread5 sub5 = new SubThread5();
Thread t = new Thread(sub5,"t1");
t.start();
t.interrupt();// 中断 t
}
}
2.yield() 线程让步
Thread.yield()
线程A yield() 那么会 让步 给 比 A优先级 高的线程 ,没有比A高度,
那么让给和A同等优先级的线程。
六、线程同步
同步语法:
七、ReentrantLock
package day0928;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
// 创建了一个Lock锁对象
static Lock lock = new ReentrantLock();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
boolean tag = false;
try {
tag = lock.tryLock(5, TimeUnit.SECONDS);// 5秒
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if(tag) {
// 获得锁成功
System.out.println(Thread.currentThread().getName() + "获得锁成功了");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + " 释放了锁");
lock.unlock();//释放锁
}
}else {
// 获得锁失败
System.out.println(Thread.currentThread().getName()+"获得锁失败了");
}
}
},"t1").start();
new Thread(new Runnable() {
@Override
public void run() {
boolean tag = false;
try {
tag = lock.tryLock(5, TimeUnit.SECONDS);// 5秒
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if(tag) {
// 获得锁成功
System.out.println(Thread.currentThread().getName() + "获得锁成功了");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + " 释放了锁");
lock.unlock();//释放锁
}
}else {
// 获得锁失败
System.out.println(Thread.currentThread().getName()+"获得锁失败了");
}
}
},"t2").start();
}
}
八、死锁
1、死锁的定义:
死锁的定义:死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们将无法推进下去,此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程成为死锁进程。
2、死锁产生条件:
互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
package day0928;
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 MyThread implements Runnable{
// 保证 一个张三和一个李四
private static Zhangsan zhangsan = new Zhangsan();
private static Lisi lisi = new Lisi();
public boolean tag = false;
@Override
public void run() {
if(tag == true) {// 张三
synchronized (zhangsan) {
zhangsan.say();// 你给我画,我就给你书
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lisi) {
zhangsan.get();// 张三获得了画
}
}
}else {// 李四
// 解决死锁的办法
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
synchronized (lisi) {
lisi.say();//你给我书,我就给你画
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (zhangsan) {
lisi.get();// 李四获得了书
}
}
}
}
}
public class TestDeadLock {
public static void main(String[] args) {
MyThread m1 = new MyThread();
m1.tag = true;
MyThread m2 = new MyThread();
m2.tag = false;
Thread tm1 = new Thread(m1,"张三");// 张三
Thread tm2 = new Thread(m2,"李四");// 李四
tm1.start();
tm2.start();
}
}
九、wait
等待
package day0928;
class MyThread1 implements Runnable{
int i = 10;// 成员变量
@Override
synchronized public void run() {
for(; i >= 0 ; i--) {
if(i == 5 && Thread.currentThread().getName().equals("t1")) {
try {
// Thread.sleep(1000);
// wait(1000);// Object类的方法
wait();//
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(i == 3) {
notify();// notifyAll()
System.out.println("我醒了");
}
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
public class TestWait {
public static void main(String[] args) {
MyThread1 mt = new MyThread1();
Thread t1 = new Thread(mt,"t1");
Thread t2 = new Thread(mt,"t2");
t1.start();
t2.start();
}
}
十、BlockingQeue
十一、守护线程