轻量级前端框架助力开发者提升项目效率与性能
630
2022-10-25
【多线程】——Thread VS Runnable
进程和线程的关系
多个线程构成一个进程,线程是进程中的一个元素,例如QQ.exe查看电脑进程的时候发现只有一个进程,但是我们可以同时和多个用户聊天交流,而且可以一边聊天,刷空间之类。对每一个用户的聊天就是一个线程,多个用户的互动构成进程。
演示一个不使用多线程的Demo,也就是单线程
public class SingleDemo{ public static void main(String[] args){ MyThread myThread = new MyThread(); myThread.run(); while(true){ System.out.println("Main方法在运行"); } }} class MyThread{ public void run(){ while (true){ System.out.println("MyThread类的run()方法在运行"); } } }
根据demo可以知道mian中的run方法永远都不可能被执行
一张图说明何为单线程和多线程!
从图中很清晰表明我们使用多线程的原因
继承Thread创建多线程
public class DemoThread{ public static void main(String[] args){ MyThread myThread = new MyThread(); myThread.start(); //通过start()开启了一个新的线程 while(true){ System.out.println("run()方法在运行"); } }}class MyThread extends Thread { public void run(){ while(true){ System.out.println("MyThread类的run()方法在运行"); } }}
显示结果
实现Runnable接口创建多线程
public class DemoRunnable{ public static void main(String[] args){ RunnableDemo runnable = new RunnableDemo(); Thread mythread = new Thread(runnable); mythread.start(); while(true){ System.out.println("main类的run()方法在运行"); } }}class RunnableDemo implements Runnable{ public void run(){ while(true){ System.out.println("RunnableDemo类的run()方法在运行"); } }}
显示结果
目前实现多线程的方式继承Thread,另一种实现Runnable接口。
上述Demo是利用Thread(Runnable target)这个构造函数实现的,Runnable是一个接口其中只有一个run()方法,在调用Thread时,看一下Thread的类结构就知道,其实实现的是接口Runnable中的方法。所以两种多线程实现方式具有多态关系。
Thread VS Runnable
先说一个例子,火车站售票会牵扯到一个资源共享的问题,资源就是车票,每个售票都相当与一个线程,假如有100张票,每张票理论上都只能买一个人,下面看Thread和Runnable的处理方式
继承Thread
public class DemoExceple{ public static void main(String[] args){ new TicketWindow().start(); new TicketWindow().start(); new TicketWindow().start(); new TicketWindow().start(); }}class TicketWindow extends Thread{ private int tickets = 100; public void run(){ while(true){ if(tickets>0){ Thread th = Thread.currentThread(); String name = th.getName(); System.out.println(name+"正在发售第"+tickets--+"张票"); } } } }
运行结果
根据这个运行结果,发现每一张票都被重复卖了四次,明显这种多线程的方式并不太适合资源共享的问题。
实现Runnable接口
public class RunnableDemoTest{ public static void main(String[] args){ TicketWindow tw = new TicketWindow(); new Thread(tw,"窗口1").start(); new Thread(tw,"窗口2").start(); new Thread(tw,"窗口3").start(); new Thread(tw,"窗口4").start(); } }class TicketWindow implements Runnable{ private int tickets = 100; public void run(){ while(true){ if(tickets>0){ Thread th = Thread.currentThread(); String th_name = th.getName(); System.out.println(th_name+"正在发售第"+tickets--+"张票"); } } }}
运行结果
根据运行结果发现使用Runnable接口刚好能解决我们资源共享的问题。
为什么Thread不行,而Runnable就可以?
Thread方式中创建了4个Thread对象,4个线程分别执行4个对象中的代码,所以4个线程是独立的去完成卖票任务
Runnable方式,同样创建了4个Thread对象,但是只有一个Runnable对象,4个Thread对象共享Runnable中的代码,因此,便会出现4个线程同时完成卖票的任务的结果。如果创建4个Runnable对象,分别做为参数传入4个Thread中,结果会和Thread方式一样的。
其实实现Runnable接口的线程中如果出现休眠,在资源共享也会出现非线程安全的问题,最根本的解决方式资源共享的问题还是同步锁(synchronized)的机制。
结论
根据上述两种情况,其实Runnable和Thread能完成相同的功能,毕竟Thread也是实现Runnable,两者根本的区别一个是继承,一个是实现。
1、Runnable相当于一个作业,而Thread才是真正的处理线程。通过new Thread(Runnable target)把作业交给线程去处理,这样达到松耦合的效果,也是符合面向对象中组合的使用。
2、Runnable可以避免Java中单继承的局限性,一个子类继承父类,不能在继承Thread实现多线程,Runnable接口刚好是完美的解决方案。
整体上来说,用Runnable比Thread好的多。
小编也是刚刚开始学习,如有错误之处还请指出,不胜感激!
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~