一、多线程
1、概述
1.1 理解线程和进程
进程时一个应用程序(软件)
线程是一个进程的执行过程/执行场景
一个进程可以启动多个线程
1.2 java中实现多线程的两种方式
- 创建一个类,直接继承
**java.lang.Thread**
重写**run()**
方法
- 在run方法中的代码运行在分支线程中
- 创建一个类,实现
**Runnable**
接口(常用)
方法
**start ()**
//启动线程**setName()**
//修改线程名字**getName()**
//得到线程名字默认线程名 Thread-0 /1/2
**Thread.currentThread()**
静态方法
//得到当前线程在哪里出现获取得就是拿的线程
Thread t1 = Thread.currentThread();
**Thread.sleep**``(``毫秒``)
静态方法
//让线程睡眠 出现在哪里就是让那个线程睡眠
**interrupt()**
//唤醒睡眠的线程
原理就是直接进去catch语句
合理结束线程
打一个布尔标记
实现线程的第三种方式 实现Callable接口
这种方式可以获取线程的返回值
1.3 代码-java实现多线程方式1 继承 Thread类
public class TreadTest001 {
public static void main(String[] args) {
A a = new A();
a.start(); // 启动线程
for (int i = 0; i < 1000; i++){
System.out.println("主线程"+i);
}
}
}
class A extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++){
System.out.println("分支线程"+i);
}
}
}
1.4 代码—-java实现多线程方式2 实现 Runnable 接口
public class ThreadTest01 {
public static void main(String[] args) {
Thread s = new Thread(new MyThread02());
s.start(); //启动线程
for (int i = 0; i < 100; i++){
System.out.println("主线程"+i);
}
}
}
class MyThread02 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++){
System.out.println("分支线程"+i);
}
}
}
1.5线程的五种状态
二、多线程并发/守护线程
1、满足条件
多线程并发
有共享数据
共享数据有修改的行为
2、解决线程安全问题
线程排队执行(不能并发)
尽量使用局部变量代替实例变量/静态变量
如果必须是实例变量,那么可以考虑多new几个对象
以上都不行采用synchronized
这种机制被称为”线程同步机制“
3、synchronized
线程同步机制语法
synchronized(共享对象) {
//同步代码块 (和谁同步,填谁和谁的同步对象)
}
synchronized
出现在实例方法上,锁的是this(不灵活)
public synchronized void doSome(){}
在静态方法上使用synchronized
表示找类锁,类锁永远只有一把
对象锁:一个对象一把锁,一百个对象一百把锁
类锁:100个对象,1把锁
sybchronized 在开发中尽量不要嵌套使用,容易死锁
局部变量不存在线程安全问题
4、守护线程
后台线程 例如:垃圾回收线程
特点:死循环,用户线程结束守护线程自动结束
语法
**setDaemon(true);**
// 变成守护线程
**t.setDaemon(true);**
//t线程变成守护线程
即使t线程里面是死循环,当主线程结束,守护线程也会结束
三、生产者和消费者
1、概述
wait()
和notify()
不是线程对象的方法
任何一个java对象都有的方法(Object自带)
wait()
和notify()
必须建立在synchroniezd基础上
2、wait()
Object o = new Object();
o.wait();
表示让正在o对象上活动的线程进入等待状态(无期限)
直到调用o.notify()方法
会释放锁
3、notify()
o.notify();
唤醒正在等待的线程
不会释放锁
4、死锁
//死锁
public class DeadThread {
public static void main(String[] args) {
Object a = new Object();
Object b = new Object();
MyThread1 one = new MyThread1(a,b); //线程对象one
MyThread2 two = new MyThread2(a,b); //线程对象two
one.start(); //启动线程one
two.start(); //启动线程two
}
}
class MyThread1 extends Thread{
Object one;
Object two;
public MyThread1(Object one, Object two) {
this.one = one;
this.two = two;
}
@Override
public void run() {
synchronized(one){
try {
Thread.sleep(2000); //睡眠2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (two){
}
}
}
}
class MyThread2 extends Thread{
Object one;
Object two;
public MyThread2(Object one, Object two) {
this.one = one;
this.two = two;
}
@Override
public void run() {
synchronized(two){
try {
Thread.sleep(2000); //睡眠两秒
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (one){
}
}
}
}
5、synchronized
有三种写法:
第一种:同步代码块 灵活
synchronized(线程共享对象){
同步代码块;
}
第二种:在实例方法上使用synchronized
表示共享对象一定是this
并且同步代码块是整个方法体
第三种:在静态方法上使用synchronized
表示找类锁。
类锁永远只有1把。
就算创建了100个对象,那类锁也只有一把
对象锁:1个对象1把锁,100个对象100把锁。
类锁:100个对象,也可能只是1把类锁。