多线程:程序同时处理多个事件(一个程序除了一条主线程main以外 还拥有很多的子线程)
单线程:之前所有的编程 都是基于单线程编程(一个程序只有一条线程(主线程main))
例子:
A一个人 每次只能做意见时间(单线程)
B一个人 可以打游戏的同时 脑袋里还想着学习(多线程)
进程:可以简单地理解成一个程序
进程是程序运行的基本单位(一个程序必须拥有一个进程(可以拥有多个))
进程拥有独立的系统资源(系统为其主动分配资源:CPU、硬盘、内存。。。)
线程:线程是组成进程(程序)的,一个进程必须拥有一条线程(主线程(main))
1、线程不能离开进程而独活
2、系统不会为线程分配资源
3、多个线程共享进程的资源
线程和进程的关系:
一个线程只属于一个进程,一个进程可以拥有很多条线程,但是至少要有一条主线程
系统会把资源分配给进程,同一个进程中的所有线程共享此资源
多线程的优点:
1、效率高
2、开销少
3、容易调度(启用)(CPU直接调度)
4、高并发性
并发:多个线程根据CPU的调度情况执行
并行:多个线程同时执行
注意:线程是抢占资源
线程的创建
java线程的创建:
1、继承Thread类
a、创建一个类 继承Thread类
b、实现run方法:子线程做的事情写在run方法里
c、启动线程:调用start()
注意:thread.run()只是普通调用方法,并没有开启线程
2、实现Runnable接口
a、创建一个类 实现Runnable接口
b、实现run方法:子线程做的事情写在run方法里
c、启动线程:创建一个Thread对象 通过该对象启动
注意:实现Runnable接口 只是拿到了run方法
//方式一:
MyThread myThread = new MyThread();
myThread.start();
//方式二:
MyThread2 myThread2 = new MyThread2();
Thread thread = new Thread(myThread2);//通过线程类的构造方法 转换
thread.start();
线程常用方法介绍:
1、curretThread():获取当前线程对象
2、sleep():休眠:可以让线程睡一会
3、join():调用该方法 等待调用的线程结束以后 再继续执行
4、yield():当前线程主动放弃CPU的资源,让其他线程去抢占,但放弃的时间不确定,有可能刚刚让出,马上自己又抢回来
5、setPriority():设置优先级:1~10,10最高,默认是5
6、isAlive():判断线程是否活着
7、interrupt():中断线程(并不是说调用以后线程就停止,该方法仅仅只是修改了线程中断的标识)
默认的中断标识:false
调用以后中断标识改为true
注意:普通线程run方法结束 该线程就停止了
线程的生命周期:从线程的创建到线程的结束
生命周期:从出生到死亡
1、创建 ---------- Thread th = new Thread();
2、就绪 ---------- 调用start() 等待CPU的调度 具备执行的资格
3、运行 ---------- 获取CPU的调度
4、结束 ---------- run()结束
5、阻塞 ---------- 正在执行的某个线程在特殊的情况下暂停了,线程在阻塞状态结束以后,并不是直接回到运行状态,而是当阻塞解除以后回到就绪状态,等待CPU的重新调度
同步:同一个资源在同一时间只允许一条线程访问
异步:所有的线程,可以在同一时间访问同一个资源
synchronized:同步锁:保证资源同一时间只能被同一条线程访问
可以锁对象,可以锁方法
synchronized单独使用:
-
代码块:如下,在多线程环境下,synchronized块中的方法获取了lock实例的monitor,如果实例相同,那么只有一个线程能执行该块内容
public class Thread1 implements Runnable { Object lock; public void run() { synchronized(lock){ ..do something } } }
-
直接用于方法: 相当于上面代码中用lock来锁定的效果,实际获取的是Thread1类的monitor。更进一步,如果修饰的是static方法,则锁定该类所有实例。
public class Thread1 implements Runnable { public synchronized void run() { ..do something } }
死锁:
产生的原因:由于同步锁操作不正确造成,代码常见表现为synchronized的嵌套
生产者和消费者案例:
生产者:
@Override
public
void
run() {
while
(
true
) {
synchronized
(Main.
lock
) {
//
注意要使用while来进行判断
while
(Main.
number
== 100) {
try
{
Main.
lock
.wait();
}
catch
(InterruptedException
e
) {
//
TODO
Auto-generated catch block
e
.printStackTrace();
}
}
Main.
number
++;
System.
out
.println(
"生产者生产了一个商品,现在一共有"
+ Main.
number
+
"个商品"
);
Main.
lock
.notifyAll();
try
{
sleep
(50);
}
catch
(InterruptedException
e
) {
//
TODO
Auto-generated catch block
e
.printStackTrace();
}
}
}
}
主程序:
public
static
int
number
= 0;
public
static
Object
lock
=
new
Object();
public
static
void
main(String[]
args
) {
Producer2
producer2
=
new
Producer2();
producer2
.start();
Consumer2
consumer2
=
new
Consumer2();
consumer2
.start();
}
Object:
wait():等待:将当前线程暂停,等待其他线程执行
notify():唤醒:将等待中的线程唤醒(恢复执行)
notifyAll():
以上3个方法主要就是用在同步锁中
sleep():休眠,属于Thread
休眠一段时间,时间到了以后会自己唤醒
wait():等待,不能自己唤醒,必须要notify()或者notifyAll()来帮助唤醒