Java多线程编程Java多线程技能

Posted BigJunOBa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程编程Java多线程技能相关的知识,希望对你有一定的参考价值。

  一、进程和多线程的概念以及线程的优点

  打开Windo任务管理器可以看到很多正在运行着的exe程序,完全可以将运行在内存中的exe文件理解成进程,进程是受操作系统管理的基本运行单元。

  线程可以理解成在进程中独立运行的子任务。比如,QQ.exe运行时就有很多的子任务在同时运行。

  使用线程,可以最大限度地利用CPU的空闲时间来处理其他的任务,CPU在人物之间不停地切换,由于切换速度非常快,所以人们感觉这些任务似乎在同时运行。也就是说看,可以在同一时间内运行更多不同种类的任务,可以大幅增加CPU的利用率。

  二、使用多线程

  一个进程正在运行时至少会有一个线程在运行。

1 package test;
2 
3 public class Test {
4 
5     public static void main(String[] args) {
6         System.out.println(Thread.currentThread().getName());
7     }
8 
9 }

  输出为:main。这里输出的main其实就是一个名称叫做main的线程在执行main()方法中的代码。

  1.继承Thread类

  实现多线程编程的方式主要有两种:一种是继承Thread类,另一种是实现Runnable接口。从Thread类的结构来看,Thread类实现了Runnable接口,它们之间具有多台关系。为了支持多继承,完全可以实现Runnable接口的形式,一边实现一边继承。

  1.1线程的调用的随机性

1 public class MyThread extends Thread {
2     @Override
3     public void run() {
4         super.run();
5         System.out.println("MyThread");
6     }
7 }
 1 package test;
 2 
 3 import com.mythread.www.MyThread;
 4 
 5 public class Run {
 6 
 7     public static void main(String[] args) {
 8         MyThread mythread = new MyThread();
 9         mythread.start();
10         System.out.println("运行结束");
11     }
12 
13 }
运行结束
MyThread

   从输出结果可以看出,代码的运行结果与代码执行顺序或调用顺序是无关的,线程是一个子任务,CPU以不确定的方式,或者说是以随机的时间来调用线程中的run方法。

  1.2 演示线程的随机性

 1 package mythread;
 2 
 3 public class MyThread extends Thread {
 4     @Override
 5     public void run() {
 6         try {
 7             for (int i = 0; i < 10; i++) {
 8                 int time = (int) (Math.random() * 1000);
 9                 Thread.sleep(time);
10                 System.out.println("run=" + Thread.currentThread().getName());
11             }
12         } catch (InterruptedException e) {
13             e.printStackTrace();
14         }
15     }
16 }
 1 package test;
 2 
 3 import mythread.MyThread;
 4 
 5 public class Test {
 6     public static void main(String[] args) {
 7         try {
 8 
 9             MyThread thread = new MyThread();
10             thread.setName("myThread");
11             thread.start();
12 
13             for (int i = 0; i < 10; i++) {
14                 int time = (int) (Math.random() * 1000);
15                 Thread.sleep(time);
16                 System.out.println("main=" + Thread.currentThread().getName());
17             }
18         } catch (InterruptedException e) {
19             e.printStackTrace();
20         }
21     }
22 }
main=main
main=main
run=myThread
main=main
run=myThread
run=myThread
main=main
main=main
run=myThread
main=main
main=main
run=myThread
main=main
main=main
run=myThread
run=myThread
run=myThread
main=main
run=myThread
run=myThread

   从输出的20个结果可以看出,Thread.java类中的start()方法通知“线程规划器”此线程已经准备就绪,等待调用线程对象的run()方法。这个过程其实就是让系统安排一个时间来调用Thread中的run()方法,也就是使线程得到运行,启动线程,具有异步执行的效果。

  1.3 同步执行

  如果调用thread.run()方法就不是异步执行了,而是同步,那么此线程对象并不交给“线程规划器”来进行处理,而是由main主线程来调用run()方法,也就是必须等run()方法中的代码执行完后才可以执行后面的代码。

 1 package extthread;
 2 
 3 public class MyThread extends Thread {
 4 
 5     private int i;
 6 
 7     public MyThread(int i) {
 8         super();
 9         this.i = i;
10     }
11 
12     @Override
13     public void run() {
14         System.out.println(i);
15     }
16 
17 }
 1 package test;
 2 
 3 import extthread.MyThread;
 4 
 5 public class Test {
 6 
 7     public static void main(String[] args) {
 8         MyThread t11 = new MyThread(1);
 9         MyThread t12 = new MyThread(2);
10         MyThread t13 = new MyThread(3);
11         MyThread t14 = new MyThread(4);
12         MyThread t15 = new MyThread(5);
13         MyThread t16 = new MyThread(6);
14         MyThread t17 = new MyThread(7);
15         MyThread t18 = new MyThread(8);
16         MyThread t19 = new MyThread(9);
17         MyThread t110 = new MyThread(10);
18         MyThread t111 = new MyThread(11);
19         MyThread t112 = new MyThread(12);
20         MyThread t113 = new MyThread(13);
21 
22         t11.start();
23         t12.start();
24         t13.start();
25         t14.start();
26         t15.start();
27         t16.start();
28         t17.start();
29         t18.start();
30         t19.start();
31         t110.start();
32         t111.start();
33         t112.start();
34         t113.start();
35 
36     }
37 
38 }
2
3
1
4
5
7
6
8
10
9
11
12
13

   从输出结果可以看出,start()方法的顺序并不代表线程启动的顺序。

  2.实现Runnable接口

  如果想要创建的线程类已经有一个父类了,这时就不能再继承自Thread类了,因为Java不支持多继承,所以就需要实现Runnable接口。

1 package myrunnable;
2 
3 public class MyRunnable implements Runnable {
4     @Override
5     public void run() {
6         System.out.println("myrunnable类中的run!");
7     }
8 }
 1 package test;
 2 
 3 import myrunnable.MyRunnable;
 4 
 5 public class Run {
 6 
 7     public static void main(String[] args) {
 8         Runnable runnable=new MyRunnable();
 9         Thread thread=new Thread(runnable);
10         thread.start();
11         System.out.println("run中的main!");
12     }
13 
14 }
run中的main!
myrunnable类中的run!

   Thread.java类的8个构造函数中,有两个可以传递Runnable接口的对象,并且由于Thread类也实现了Runnable接口,所以也就意味着构造函数Thread(Runnable target)不光可以传入Runnable接口的对象, 还可以传入一个Thread类的对象,这样做完全可以将一个Thread对象中的run()方法交由其他的线程进行调用。

  3.实例变量与线程安全

  自定义线程类中的实例变量针对其他线程可以有共享与不共享之分。

  3.1 不共享数据

  3.2 共享数据

  4.留意i--与System.out.println()的异常

  三、currentThread()方法

  四、isAlive()方法

  五、sleep()方法

  六、getId()方法

  七、停止线程

  1.停止不了的线程

  2.判断线程是否是停止状态

  3.能停止的线程--异常法

  4.在沉睡中停止

  5.能停止的线程--暴力停止

  6.方法stop()与java.lang.ThreadDeath异常

  7.释放锁的不良后果

  8.使用return停止线程

  八、暂停线程

  1.suspend与resume方法的使用

  2.suspend与resume方法的缺点--独占

  3.suspend与resume方法的缺点--不同步

  九、yield()方法

  十、线程的优先级

  1.线程优先级的继承特性

  2.优先级具有规则性

  3.优先级具有随机性

  4.看谁运行得快

  十一、守护线程

以上是关于Java多线程编程Java多线程技能的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程编程核心——Java多线程技能

《Java多线程编程核心技术》多线程技能

Java多线程编程Java多线程技能

java多线程编程

最全Java并发编程技能:多线程+线程池+线程锁+并发工具+并发容器

Java进阶多线程编程,程序员必备技能!