java 多线程的三种构建方法
java 多线程的三种构建方法
继承thread类创建线程类
public class thread extends object implements runnable
- 定义thread类的子类,并重写其run()方法
- 创建thread子类的实例,即创建了线程对象
- 调用线程对象的start()方法启动线程
public class firstthread extends thread { public void run(){ for(int i=0;i<100;i++){ /* * thread类已经继承了object * object类创建了name选项 并且有其getname(),setname()方法 * 在继承thread的类里面使用时只需要用this引用 */ system.out.println(this.getname()+" "+i); } } public static void main(string[] args) { for(int i=0;i<100;i++){ system.out.println(thread.currentthread().getname()+" "+i); if(i==20){ new firstthread().start(); new firstthread().start(); } } } }
thread类已经继承了object
object类创建了name选项 并且有其getname(),setname()方法
在继承thread的类里面使用时只需要用this引用
上面两个副线程和主线程随机切换,又因为使用的是继承thread的类所以两个副线程不能共享资源
start()方法调用后并不是立即执行多线程代码,而是使得该线程编程可运行状态,什么时候运行是由操作系统决定的
实现runnable接口创建线程类
public thread() public thread(runnable target) public thread(runnable target,string name)
- 定义runnable接口的实现类,并重写该接口的run()方法
- 创建runnable实现类的实例,并以此作为thread的target来创建thread对象,该thread对象才是真正的线程对象。
public class secondthread implements runnable { public void run(){ for(int i=0;i<100;i++){ system.out.println(thread.currentthread().getname()+" "+i); } } public static void main(string[] args) { for(int i=0;i<100;i++){ system.out.println(thread.currentthread().getname()+" "+i); if(i==20){ secondthread st=new secondthread(); //通过new thread(target,name)创建线程 new thread(st,"新线程1").start(); new thread(st,"新线程2").start(); } } } }
上面的结果是两个副线程和主线程随机切换,但是并没有共享资源,因为他们根本没有能用来共享的资源。
start()方法调用后并不是立即执行多线程代码,而是使得该线程编程可运行状态,什么时候运行是由操作系统决定的
继承thread类和创建runnable接口的共享资源详解
在只有可以用来共享的资源时候,也就是同用一个实例化对象。两个创建方式在共享资源时才会有所区别,否则它们都不会共享资源共享资源通常用private static 修饰符来修饰。
class thread1 extends thread{ private int count=5; private string name; public thread1(string name) { this.name=name; } public void run() { for (int i = 0; i < 5; i++) { system.out.println(name + "运行 count= " + count--); try { sleep((int) math.random() * 10); } catch (interruptedexception e) { e.printstacktrace(); } } } } public class main { public static void main(string[] args) { thread1 mth1=new thread1("a"); thread1 mth2=new thread1("b"); mth1.start(); mth2.start(); } }
b运行 count= 5 a运行 count= 5 b运行 count= 4 b运行 count= 3 b运行 count= 2 b运行 count= 1 a运行 count= 4 a运行 count= 3 a运行 count= 2 a运行 count= 1
正是因为有了private int count=5;一句才有了共享资源,但这是继承thread类的子类,并不能共享资源
class thread2 implements runnable{ private int count=15; public void run() { for (int i = 0; i < 5; i++) { system.out.println(thread.currentthread().getname() + "运行 count= " + count--); try { thread.sleep((int) math.random() * 10); } catch (interruptedexception e) { e.printstacktrace(); } } } } public class main { public static void main(string[] args) { thread2 my = new thread2(); new thread(my, "c").start();//同一个mt,但是在thread中就不可以,如果用同一个实例化对象mt,就会出现异常 new thread(my, "d").start(); new thread(my, "e").start(); } }
c运行 count= 15 d运行 count= 14 e运行 count= 13 d运行 count= 12 d运行 count= 10 d运行 count= 9 d运行 count= 8 c运行 count= 11 e运行 count= 12 c运行 count= 7 e运行 count= 6 c运行 count= 5 e运行 count= 4 c运行 count= 3 e运行 count= 2
同样的正是因为有了private int count=15这个共同的实例化对象,实现runnable的类才可以共享资源
那么为什么继承thread类的子类实现runable接口的类在共享资源时有区别呢?
因为java中只能支持单继承,单继承特点意味着只能有一个子类去继承 而runnabl接口后可以跟好多类,便可以进行多个线程共享一个资源的操作
使用callable和future创建线程
callable怎么看起来都像runnable接口的增强版,callable有一个call()方法相当于runnable的run()方法,但是功能却更加强大:
call()方法可以有返回值
call()方法可以声明抛出异常
callable接口有泛型限制,callable接口里的泛型形参类型与call()方法的返回值类型相同。 而且callable接口是函数式接口,因此可使用lambda表达式创建callable对象 runnable接口也是函数式接口,因此也可以使用lambda表达式创建runnable对象
- 创建callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,再创建callable实现类的实例
- 使用futuretask类来包装callable对象,该futuretask对象封装了该callable对象的call()方法
- 使用futuretask类对象作为thread对象的target创建并启动新线程
- 调用futuretask对象的get()方法来获得子线程结束后的返回值
public class thirdthread implements callable<integer> { public integer call(){ int i=0; for(;i<100;i++){ system.out.println(thread.currentthread().getname()+" "+i); } return i; } public static void main(string[] args){ thirdthread tt=new thirdthread(); futuretask<integer> task=new futuretask<>(tt); thread t=new thread(task,"有返回值的线程"); for(int i=0;i<100;i++){ system.out.println(thread.currentthread().getname()+" "+i); if(i==20){ t.start(); } } try{ system.out.println("返回值是:"+task.get()); }catch(exception e){ e.printstacktrace(); } } }
使用lambda表达式的callable和future创建的线程
public class thirdthread{ public static void main(string[] args){ thirdthread tt=new thirdthread(); //先使用lambda表达式创建callable<integer>对象 //使用futuretask封装callable对象 futuretask<integer> task=new futuretask<integer>((callable<integer>)()->{ int i=0; for(;i<100;i++){ system.out.println(thread.currentthread().getname()+"的循环变量i的值:"+i); } return i; }); for(int i=0;i<100;i++){ system.out.println(thread.currentthread().getname()+"的循环变量i的值:"+i); if(i==20){ new thread(task,"有返回值的线程").start(); } } try{ system.out.println("子线程的返回值"+task.get()); }catch(exception e){ e.printstacktrace(); } } }
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!