Java多线程应用
- 什么是进程?
进程是操作系统的结构,是一次程序的执行,是程序在一个数据集合运行的过程,是系统的进行资源分配和调度的独立单位? - 什么是线程?
线程是进程中具体的搬运工,由进行分配资源进行调度,单个线程必须一个执行完成后,才能执行另外一个,但是多线程操作系统windows,就可以在一个任务执行处于等待的时候,cpu空闲的时间去执行另外一个任务,各个任务之前的快速切换,可以造成,多任务同时执行的效果。 - 实现线程的方法
3.1 继承Thread类
package threadMainTest;
public class ManyThread extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
}
}
主方法调用
package threadMainTest;
public class ThreadMainTest {
public static void main(String[] args) throws InterruptedException {
ManyThread mT = new ManyThread();
}
}
3.2 实现Runnable接口
4. package threadMainTest;
5.
6. public class MyRunnable implements Runnable{
7.
8. @Override
9. public void run() {
10. System.out.println(“使用实现runnable方式来实现线程”);
11. }
12.
13. }
主方法调用
package threadMainTest;
public class ThreadMainTest {
public static void main(String[] args) throws InterruptedException {
MyRunnable mr = new MyRunnable();
Thread tr = new Thread(mr);
tr.start();
}
}
因为Thread类是继承的Runnable接口,所以这儿Thread构造函数,不仅可以传入一个Runnable对象,还可以传入一个Thread对象。
4. 线程常用的方法
4.1 currentThread()方法,返回当前代码块正在被哪个线程调用
5 package threadMainTest;
6 public class MyThread extends Thread{
7 public MyThread() {
8 System.out.println(“CountOperate begin”);
9 System.out.println(“Thread.currentThread().getName()=”+Thread.currentThread().getName());
10 System.out.println(“this.getName()”+this.getName());
11 System.out.println(“CountOperate end”);
12 }
13 @Override
14 public void run() {
15 System.out.println(“run begin”);
16 System.out.println(“Thread.currentThread().getName()=”+Thread.currentThread().getName());
17 System.out.println(“this.getName()=”+this.getName());
18 System.out.println(“run end”);
19 }
20 }
主方法调用
21 MyThread my = new MyThread();
22 Thread t = new Thread(my);
23 t.setName(“A”);
24 t.start();
结果展示
25 CountOperate begin
26 Thread.currentThread().getName()=main
27 this.getName()Thread-0
28 CountOperate end
29 run begin
30 Thread.currentThread().getName()=A
31 this.getName()=Thread-0
32 run end
如果将主方法代码修改为下面
MyThread my = new MyThread();
Thread t = new Thread(my);
t.setName(“A”);
t.start();
my.setName(“A”);
my.start();
结果展示
CountOperate begin
Thread.currentThread().getName()=main
this.getName()Thread-0
CountOperate end
run begin
Thread.currentThread().getName()=A
this.getName()=A
run end
run begin
Thread.currentThread().getName()=A
this.getName()=A
4.2 isActive()方法,用于显示线程的活跃状态,活跃状态就是线程已经启动并且尚未终止。线程处于正在运行或者存在运行的状态,就认为线程是存活的,如果存活返回true,否则返回false.
4.3 Sleep()是在指定的毫秒数内,让正在执行的线程休眠,this.currentThrad()就是指正在执行的线程
4.4 Getid()取得线程唯一的标识符,即表示线程的ID值
5. 停止线程
5.1 stop(),suspend(),resume(),都可以用于终止线程,但是他们都是强制终止线程,不安全,所以已经被移除(deprecated),在未来的JAVA版本中也将不可以使用,目前使用Interrupt(),终止线程,但是不会终止正在运行的线程,需要加入一个判断才能完成线程的终止。
package threadMainTest;
public class isThreadActive extends Thread{
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println(“i=”+ i++);
}
}
}
主函数调用
package threadMainTest;
public class isThreadActive extends Thread{
@Override
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println(“i=”+ i++);
}
}
}
结果展示
i=378
i=380
i=382
i=384
i=386
i=388
i=390
i=392
i=394
i=396
i=398
i=400
i=402
i=404
线程并没有被关闭,是因为interrupt()不能关闭正在运行的线程
5.2 interrupted() 测试当前线程是否已经被中断(当判断完毕后,如果线程被中断,会清楚当前被中断的状态),inInterrupted()测试线程是否已经被中断.没有清除功能
6. package threadMainTest;
7.
8. public class Run2 {
9. public static void main(String[] args) {
10. Thread.currentThread().interrupt();
11. System.out.println(“是否停止1?”+Thread.interrupted());
12. System.out.println(“是否停止2?”+Thread.interrupted());
13. }
14. }
结果展示
15. 是否停止1?true
16. 是否停止2?false
如果是inInterrupted()
17. package threadMainTest;
18.
19. public class Run2 {
20. public static void main(String[] args) {
21. try {
22. isThreadActive thread = new isThreadActive();
23. thread.start();
24. Thread.sleep(5);
25. thread.interrupt();
26. System.out.println(“是否停止1?”+thread.isInterrupted());
27. System.out.println(“是否停止2?”+thread.isInterrupted());
28. } catch (InterruptedException e) {
29.
30. e.printStackTrace();
31. }
32. }
33. }
结果展示
34. i=637
35. 是否停止1?true
36. 是否停止2?true
37. i=638
38. i=639
5.3 调用interrupt方法后,后for后面的语句还是在运行(如何使线程停止,程序不运行)
6 package thread;
7
8 public class ThreadTest extends Thread{
9 @Override
10 public void run() {
11 int time = 0;
12 for (int i = 0; i < 500000; i++) {
13 if(this.interrupted()) {
14 System.out.println("已经是停止状态了,我要退出了 ");
15 break;
16 }
17 System.out.println("i = " + (i+1));
18 }
19 System.out.println(“还是在运行”);
20 }
21 }
展示结果
22 i = 394330
23 i = 394331
24 i = 394332
25 已经是停止状态了,我要退出了
26 还是在运行
27 end!
如何使停止线程后程序就不在运行,使用异常退出
28 package thread;
29 public class ThreadTest extends Thread{
30 @Override
31 public void run() {
32 super.run();
33 try {
34 for (int i = 0; i < 500000; i++) {
35 if(this.interrupted()) {
36 System.out.println("已经是停止状态了,我要退出了 ");
37 throw new InterruptedException();
38 }
39 System.out.println("i = " + (i+1));
40 }
41 System.out.println(“还是在运行”);
42 } catch (InterruptedException e) {
43 System.out.println(“进入了线程的异常捕获方法”);
44 e.printStackTrace();;
45 }
46 }
47 }
主方法
48 package thread;
49
50 public class ThreadMainTest {
51 public static void main(String[] args) {
52 try {
53 ThreadTest thread = new ThreadTest();
54 thread.start();
55 Thread.sleep(100);
56 thread.interrupt();
57 } catch (InterruptedException e) {
58 System.out.println(“main catch”);
59 e.printStackTrace();
60 }
61 System.out.println(“end!”);
62 }
63 }
结果展示
64 i = 341617
65 已经是停止状态了,我要退出了
66 进入了线程的异常捕获方法
67 end!
68 java.lang.InterruptedException
69 at thread.ThreadTest.run(ThreadTest.java:11)
如何停止沉睡中的线程
package thread;
public class ThreadTest extends Thread{
@Override
public void run() {
super.run();
try {
System.out.println(“run begin”);
Thread.sleep(200000);
System.out.println(“run end”);
} catch (InterruptedException e) {
System.out.println(“线程停止,目前状态为:” + this.isInterrupted());
e.printStackTrace();
}
}
}
展示结果:
run begin
线程停止,目前状态为:false
end!
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at thread.ThreadTest.run(ThreadTest.java:9)
如果先执行interrupt停止再sleep会怎么样
package thread;
public class ThreadTest extends Thread{
@Override
public void run() {
super.run();
try {
for (int i = 0; i < 500; i++) {
System.out.println("i= " + (i+1));
}
System.out.println(“run begin”);
Thread.sleep(200000);
System.out.println(“run end”);
} catch (InterruptedException e) {
System.out.println(“先停止,再遇到Sleep,然后进入catch”);
e.printStackTrace();
}
}
}
主方法
package thread;
public class ThreadMainTest {
public static void main(String[] args) {
ThreadTest thread = new ThreadTest();
thread.start();
thread.interrupt();
System.out.println(“end!”);
}
}
使用return停止线程
package thread;
public class ThreadTest extends Thread{
@Override
public void run() {
super.run();
while(true) {
if(this.isInterrupted()) {
System.out.println(“停止了”);
return;
}
System.out.println("time= " + System.currentTimeMillis());
}
}
}
主方法:
package thread;
public class ThreadMainTest {
public static void main(String[] args) throws InterruptedException {
ThreadTest thread = new ThreadTest();
thread.start();
Thread.sleep(2000);
thread.interrupt();
}
}
结果展示:
time= 1542850294016
time= 1542850294016
time= 1542850294016
time= 1542850294016
time= 1542850294016
time= 1542850294016
time= 1542850294016
停止了
不过还是建议用抛异常的方式来停止线程,因为Catch块中还可以将异常向上抛,使线程停止的事件得以传播!
6. 暂停线程
6.1 suspend()暂停现场,resume()恢复线程使用
7. package threadMainTest;
8.
9. public class ThreadMainTest {
10. @SuppressWarnings(“deprecation”)
11. public static void main(String[] args) throws InterruptedException {
12. MyThread my = new MyThread();
13. my.start();
14. Thread.sleep(5000);
15. my.suspend();//已经被移除,可以用但是还是有缺陷,在被调用过程中不会释放所占用的锁,容易造成死锁
16. System.out.println("A= " + System.currentTimeMillis()+ "A= " + my.getI());
17. System.out.println("B= " + System.currentTimeMillis()+ "B= " + my.getI());
18. my.resume();
19. Thread.sleep(5000);
20. my.suspend();
21. System.out.println("C= " + System.currentTimeMillis()+ "C= " + my.getI());
22. System.out.println("D= " + System.currentTimeMillis()+ "D= " + my.getI());
23. }
24. }
结果展示
25. A= 1542871355220A= -1084856100
26. B= 1542871355220B= -1084856100
27. C= 1542871405220C= 929579568
28. D= 1542871405220D= 929579568
6.2 Yield()放弃当前的CPU,资源,让给其它任务来占用CPU
package thread;
public class ThreadTest extends Thread{
@Override
public void run() {
long time = System.currentTimeMillis();
int count = 0 ;
while(count < 500000) {
//Thread.yield();
count ++;
}
long endTime = System.currentTimeMillis();
System.out.println(“用时” + (endTime-time) + “毫秒”);
}
}
结果显示:
使用Thread.yield()后,把CPU让给其他资源,导致速度变慢
6.3 优先级
6.3.1 继承性
线程的优先级具有继承性,A调用B线程,所以B线程的优先级跟A线程一样
package threadMainTest;
public class MyThread extends Thread{
@Override
public void run() {
System.out.println("MyThread run is priority = " + this.getPriority());
}
}
主方法调用
package threadMainTest;
public class ThreadMainTest {
public static void main(String[] args) throws InterruptedException {
System.out.println("main thread begin priority = " + Thread.currentThread().getPriority());
Thread.currentThread().setPriority(6);
System.out.println("main thread begin priority = " + Thread.currentThread().getPriority());
new MyThread().start();
}
}
结果
main thread begin priority = 5
main thread begin priority = 6
MyThread run is priority = 6
6.3.2使用setPriority()方法设置优先级
高优先级的线程大部分总是先执完,但是并不代表所有高优先级的线程会限制性,线程的优先级与代码的调用顺序无关,线程执行具有随机性,不一定每次高的线程都先执行
6.3.3守护线程
守护线程,是伴随着需要守护的线程的,当最后一个需要守护的线程停止时,守护线程才会随着JVM结束,最典型的的就是GC垃圾回收机制