线程
串行单线程执行
在食堂打饭的时候,食堂安排一个打饭大妈打饭,所有同学都排成一个队形,打饭大妈相当于线程,同学打饭相当于任务,这种一个大妈给一群站好队形的同同学打饭相当于java中的单线程串行执行任务。
串行执行的缺点很明显,当一个同学选菜慢的情况下,效率低下,后面的同学早已不耐烦了
并行多线程执行
为了解决上述问题,食堂打算聘请和学生数目一样多的打饭大妈,同时给同学打饭,这样的话同学倒是开心了,很快就能吃上饭,但是食堂承受不了了,因为食堂需要开更多的打饭窗口以及给大妈的工资,映射到多线程中也一样,如果每个任务都创建一个线程来处理的话,任务数量一旦多了,内存就会有很大的负担,甚至可能宕机。
线程池
为了解决上述问题,食堂又做了改进,就是先确定好打饭大妈的数量,然后让同学们排队,每个打饭大妈打完一次饭就叫队列中的下一个。映射到java中我们创建指定数量的线程,然后把任务放到一个队列中去处理,当每个线程处理完任务后就会去队列中取下一个任务处理,可以把线程重复利用,因为线程的创建也是消耗资源的。
所以结论就是:在一定范围内增加线程数量的确可以提升系统的处理能力,但是过多的创建线程将会降低系统的处理速度,如果无限制的创建线程,将会使系统崩溃。
对于一个程序,默认只有一个进程,按照一定的顺序进行操作
但是,如果对一个事件操作很慢,但是cpu内存又足够大去对另一个事件操作
就需要进行并事件操作,也就是多进程,同时操作不同的事件,节省了时间,使得cpu在同样的时间里完成更多的事件
线程的实现
线程实现有两种方法
- 继承Thread类,重写run()方法
- 实现Runnable接口,实现run()方法
几个重要的函数
Thread.currentThread().getName()获取当前线程的名字.
对于线程的名字,如果没有去给他命名,系统自带为他命名
start()
启动一个线程
继承Thread
package Experiment;
public class E13{
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
MyThread t2 = new MyThread();
t2.start();
}
}
class MyThread extends Thread{
public void run(){
for(int i=1;i<20;i++){
System.out.println(Thread.currentThread().getName()+"-->"+i);
}
}
}
输出
Thread-0-->1
Thread-1-->1
Thread-0-->2
Thread-1-->2
Thread-0-->3
Thread-1-->3
Thread-1-->4
Thread-1-->5
Thread-0-->4
Thread-1-->6
Thread-1-->7
Thread-0-->5
Thread-1-->8
Thread-1-->9
Thread-0-->6
Thread-1-->10
Thread-0-->7
Thread-1-->11
Thread-0-->8
Thread-1-->12
Thread-0-->9
Thread-1-->13
Thread-0-->10
Thread-1-->14
Thread-0-->11
Thread-1-->15
Thread-0-->12
Thread-1-->16
Thread-0-->13
Thread-1-->17
Thread-1-->18
Thread-0-->14
Thread-1-->19
Thread-0-->15
Thread-1-->20
Thread-0-->16
Thread-0-->17
Thread-0-->18
Thread-0-->19
Thread-0-->20
可以发现有40条记录,线程0是e1线程,线程1是e2线程
他们是同时进行操作的
Runnable接口
package Experiment;
public class E13{
public static void main(String[] args) {
Thread t3 = new Thread(new Task());
t3.start();
Thread t4 = new Thread(new Task());
t4.start();
}
}
class Task implements Runnable{
public void run() {
for(int i=1;i<=20;i++) {
System.out.println(Thread.currentThread().getName()+"-->"+i);
}
}
}
输出
Thread-1-->1
Thread-0-->1
Thread-1-->2
Thread-0-->2
Thread-1-->3
Thread-0-->3
Thread-1-->4
Thread-0-->4
Thread-1-->5
Thread-0-->5
Thread-1-->6
Thread-0-->6
Thread-1-->7
Thread-0-->7
Thread-1-->8
Thread-0-->8
Thread-1-->9
Thread-0-->9
Thread-1-->10
Thread-0-->10
Thread-1-->11
Thread-0-->11
Thread-1-->12
Thread-0-->12
Thread-1-->13
Thread-0-->13
Thread-0-->14
Thread-0-->15
Thread-0-->16
Thread-1-->14
Thread-1-->15
Thread-1-->16
Thread-1-->17
Thread-1-->18
Thread-1-->19
Thread-1-->20
Thread-0-->17
Thread-0-->18
Thread-0-->19
Thread-0-->20
发现Runnable接口和继承Thread的效果差不多
区别
①由于Java不允许多继承,所以继承了Thread类,就不能继承其他类,而Runnable接口可以继续接其他接口
②实现Runnable接口的线程类的多个线程,适合访问同一变量,而Thread不能(多窗口买票问题)
③Thread采用了Runnable接口
第②点的原因是两者的启动方式不同,Runnable线程类是实例化一个对象O后,多次进行new Thread(O).start(),对象,这几个线程属于同一个对象,对象的成员变量是同一个
而对于Thread线程类启动多个线程需要new MyThread().start();每个线程启动都对应不同的对象,他们的成员变量是独立的
而如果Thread加了synchronized之后也是可以访问同一个变量的
所以,只是Thread不适合去访问同一个变量
从Thread源码中也可以看到,当以Thread方式去实现资源共享时,实际上源码内部是将thread向下转型为了Runnable,实际上内部依然是以Runnable形式去实现的资源共享
比如
package Experiment;
public class E13{
public static void main(String[] args) {
MyThread t=new MyThread();//只能使用同一个t
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}
class MyThread implements Runnable{
private int ticket=100;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
if(ticket>0){
System.out.println(Thread.currentThread().getName()+"...is saling,余票:"+ticket--);
}
}
}
}
输出
Thread-0...is saling,余票:100
Thread-2...is saling,余票:98
Thread-2...is saling,余票:95
Thread-1...is saling,余票:99
Thread-2...is saling,余票:94
Thread-0...is saling,余票:97
Thread-3...is saling,余票:96
Thread-0...is saling,余票:91
Thread-2...is saling,余票:92
Thread-1...is saling,余票:93
Thread-2...is saling,余票:88
Thread-2...is saling,余票:86
Thread-2...is saling,余票:85
Thread-0...is saling,余票:89
Thread-3...is saling,余票:90
Thread-0...is saling,余票:83
Thread-2...is saling,余票:84
Thread-1...is saling,余票:87
Thread-2...is saling,余票:80
Thread-0...is saling,余票:81
Thread-3...is saling,余票:82
Thread-0...is saling,余票:77
Thread-2...is saling,余票:78
Thread-1...is saling,余票:79
Thread-2...is saling,余票:74
Thread-0...is saling,余票:75
Thread-3...is saling,余票:76
Thread-0...is saling,余票:71
Thread-2...is saling,余票:72
Thread-1...is saling,余票:73
Thread-2...is saling,余票:68
Thread-0...is saling,余票:69
Thread-3...is saling,余票:70
Thread-0...is saling,余票:65
Thread-2...is saling,余票:66
Thread-1...is saling,余票:67
Thread-2...is saling,余票:62
Thread-2...is saling,余票:60
Thread-0...is saling,余票:63
Thread-3...is saling,余票:64
Thread-3...is saling,余票:57
Thread-0...is saling,余票:58
Thread-2...is saling,余票:59
Thread-1...is saling,余票:61
Thread-2...is saling,余票:54
Thread-0...is saling,余票:55
Thread-3...is saling,余票:56
Thread-0...is saling,余票:51
Thread-2...is saling,余票:52
Thread-1...is saling,余票:53
Thread-2...is saling,余票:48
Thread-0...is saling,余票:49
Thread-3...is saling,余票:50
Thread-0...is saling,余票:45
Thread-2...is saling,余票:46
Thread-1...is saling,余票:47
Thread-2...is saling,余票:42
Thread-0...is saling,余票:43
Thread-3...is saling,余票:44
Thread-0...is saling,余票:39
Thread-2...is saling,余票:40
Thread-1...is saling,余票:41
Thread-2...is saling,余票:36
Thread-0...is saling,余票:37
Thread-3...is saling,余票:38
Thread-0...is saling,余票:33
Thread-2...is saling,余票:34
Thread-1...is saling,余票:35
Thread-2...is saling,余票:30
Thread-0...is saling,余票:31
Thread-3...is saling,余票:32
Thread-0...is saling,余票:27
Thread-2...is saling,余票:28
Thread-1...is saling,余票:29
Thread-2...is saling,余票:24
Thread-0...is saling,余票:25
Thread-3...is saling,余票:26
Thread-0...is saling,余票:21
Thread-2...is saling,余票:22
Thread-1...is saling,余票:23
Thread-2...is saling,余票:18
Thread-0...is saling,余票:19
Thread-0...is saling,余票:15
Thread-3...is saling,余票:20
Thread-0...is saling,余票:14
Thread-2...is saling,余票:16
Thread-1...is saling,余票:17
Thread-2...is saling,余票:11
Thread-0...is saling,余票:12
Thread-3...is saling,余票:13
Thread-0...is saling,余票:8
Thread-2...is saling,余票:9
Thread-1...is saling,余票:10
Thread-2...is saling,余票:5
Thread-0...is saling,余票:6
Thread-3...is saling,余票:7
Thread-3...is saling,余票:1
Thread-0...is saling,余票:2
Thread-2...is saling,余票:3
Thread-1...is saling,余票:4
可以发现这100条是一起操作的,没有重复
而对于继承
package Experiment;
public class E13{
public static void main(String[] args) {
MyThread t=new MyThread();//只能使用同一个t
//10个线程
new MyThread().start();
new MyThread().start();
new MyThread().start();
new MyThread().start();
}
}
class MyThread extends Thread{
private int ticket=10;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
if(ticket>0){
System.out.println(Thread.currentThread().getName()+"...is saling,余票:"+ticket--);
}
}
}
}
输出
Thread-2...is saling,余票:10
Thread-3...is saling,余票:10
Thread-1...is saling,余票:10
Thread-1...is saling,余票:9
Thread-4...is saling,余票:10
Thread-3...is saling,余票:9
Thread-2...is saling,余票:9
Thread-3...is saling,余票:8
Thread-4...is saling,余票:9
Thread-1...is saling,余票:8
Thread-4...is saling,余票:8
Thread-3...is saling,余票:7
Thread-2...is saling,余票:8
Thread-3...is saling,余票:6
Thread-4...is saling,余票:7
Thread-1...is saling,余票:7
Thread-4...is saling,余票:6
Thread-3...is saling,余票:5
Thread-2...is saling,余票:7
Thread-3...is saling,余票:4
Thread-4...is saling,余票:5
Thread-1...is saling,余票:6
Thread-4...is saling,余票:4
Thread-3...is saling,余票:3
Thread-2...is saling,余票:6
Thread-3...is saling,余票:2
Thread-4...is saling,余票:3
Thread-1...is saling,余票:5
Thread-4...is saling,余票:2
Thread-4...is saling,余票:1
Thread-3...is saling,余票:1
Thread-2...is saling,余票:5
Thread-2...is saling,余票:4
Thread-2...is saling,余票:3
Thread-2...is saling,余票:2
Thread-2...is saling,余票:1
Thread-1...is saling,余票:4
Thread-1...is saling,余票:3
Thread-1...is saling,余票:2
Thread-1...is saling,余票:1
每个线程是独立的
只是在同一时间完成4个线程而已
如果加了synchronized (this),那么两者都可以实现资源共享了
但既然Thread是采用了Runnable接口,那么Thread有什么好处,为什么创建Thread ?