java多线程编程(三)- 线程的创建
一:线程说明
1,Java虚拟机允许应用程序并发的运行多个执行线程。
2,线程都有自己的优先级,新线程会继承创建它的线程优先级。
3,线程可以为守护线程和用户线程,如java资源回收线程为守护线程。当且仅当创建线程为守护线程时,新程序才是守护线程。
个人总结:
a:创建新线程只能通过Thread类或其子类,但可以通过实现Runnable接口和Callable接口写具体的执行代码。
b:新创建的线程只能通过start()方法启动,而Runnable接口无start()方法,因此需借助Thread类才能创建;
二:Thread类
1, java.lang.Thread类的继承关系
上图为 java.lang.Thread类的继承关系,Thread类实现了java.lang.Runnable接口。
2,java.lang.Thread类的构造方法
从java.lang.Thread类的构造方法中,看出:
a:可以创建新线程时命名。
b:可以将实现Runnable接口的类作为参数,传入新线程。
c:可以将新线程加入线程组,具体应用待研究。
3,java.lang.Thread类创建新线程
通过继承Thread类,并重写run()方法可以创建新线程对象,使用该对象start()方法启动线程。
1 package com.thread.www; 2 3 class PrimeThread extends Thread{ 4 public PrimeThread(String thName) { 5 this.setName(thName); 6 } 7 8 @Override 9 public void run() { 10 System.out.println("线程重要属性如下:"); 11 System.out.println(" run 线程ID ="+this.getId()); 12 System.out.println(" run 线程名称 ="+this.getName()); 13 System.out.println(" run 优先级 ="+this.getPriority()); 14 System.out.println(" run 活跃状态 ="+this.isAlive()); 15 } 16 } 17 18 public class Test1NewThread { 19 public static void main(String[] args) { 20 PrimeThread name = new PrimeThread("jack"); 21 22 //启动执行线程 23 name.start(); 24 } 25 }
执行结果:
二:Runable接口
java.lang.Runable接口是为了执行代码提供一个公共协议。大多数情况下,如果不需要重写Thread类中除run()的其它方法,用这种方式创建新线程,需要:
a:创建实现java.lang.Runnable接口的对象,重写run()方法。
b:创建Thread类或其子类的对象,一般是用Thread类的对象,并且将a中创建对象作为参数传入该对象构造方法,再使用该对象start()方法启动线程。
1 package com.thread.www; 2 3 class PrimeRun implements Runnable{ 4 5 @Override 6 public void run() { 7 System.out.println("run do .."); 8 } 9 } 10 11 public class Test2NewThread { 12 13 public static void main(String[] args) { 14 //1: 15 PrimeRun name = new PrimeRun(); 16 17 //2:需要创建Thread对象后,name作为参数传入,才能执行name.run() 18 new Thread(name).start(); 19 } 20 } 21 /* 22 * 创建PrimeRun对象,只是建立线程的参数,真正创建线程并启动还需要Thread类或其子类 23 */
三:Callable接口创建执行线程的执行域
通过实现Callable接口方式创建新线程,可以返回的线程运行结果或抛出的异常,具体实现需要:
a:实现java.util.concurrent.Callalbe接口,并重写call()方法。
b:创建java.util.concurrent.FutrueTask类的对象,并将a中创建对象作为参数传入该对象构造方法,FuntrueTask类实现了Runnable接口。
c:创建Thread类或其子类的对象,一般是用Thread类的对象,并将b中创建的对象作为参数传入该对象构造方法,使用该对象start()方法启动线程。
1 package com.thread.www; 2 3 import java.util.concurrent.Callable; 4 import java.util.concurrent.FutureTask; 5 6 class PrimeCall implements Callable<Integer>{ 7 8 //call() 方法区别 run(),可以返回结果,可以抛出异常 9 @Override 10 public Integer call() throws Exception { 11 int sum = 0; 12 for (int i = 0; i < 1000000; i++) { 13 sum +=i; 14 } 15 return sum; 16 } 17 } 18 19 public class Test3NewThread { 20 21 public static void main(String[] args) { 22 int sumCall = 0; 23 //1: 24 PrimeCall pCall = new PrimeCall(); 25 26 //2:Callable未实现Runable,不能直接作为Thread的参数,需要FutureTask过渡以及接收run()返回结果 27 FutureTask<Integer> futureCall = new FutureTask<Integer>(pCall); 28 29 //3:FutureTask实现了Runable,所以可以作为Thread的参数 30 new Thread(futureCall).start(); 31 32 try { 33 sumCall = futureCall.get(); 34 // sumCall = futureCall.get(50, TimeUnit.NANOSECONDS);//可以设置等待结果的超时时间 35 } catch (Exception e) { 36 e.printStackTrace(); 37 } 38 39 System.out.println(sumCall); 40 41 } 42 43 }
参考资料:https://docs.oracle.com/javase/8/docs/api/
http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
https://www.cnblogs.com/baizhanshi/p/6425209.html