JAVA多线程之Thread&&Runnable
来源:互联网 发布:windows系统启动 efi 编辑:程序博客网 时间:2024/05/29 13:21
看了个视频,嗯,记录下加深下理解。。。java实现多线程的两种方式:继承thread类,这种方式的缺陷就是java的单继承导致的;还有一种方式就是实现Runnable接口,这种方式避免了thread方式由于java单继承带来的缺陷。需要知道的是线程启动后会抢占CPU资源,如果当前new了一个线程,线程就会进入创建的状态,然后我们启动这个线程,thread.start(),这个时候这个线程就会处在就绪状态,如果当前能获取到CPU资源,然后就会处在运行状态,如果这个时候执行了sleep方法或者一些阻塞事件,会导致线程处于阻塞状态,然后sleep到一定时间后阻塞解除,会继续排队到就绪状态,继续等待当前释放CPU释放资源,如果run方法执行完毕的话,那么线程终止,自动销毁。这也是为什么不加synchronized的话会出现乱序的情况。因为你虽然进入了线程队列,但是当前cpu资源不一定是被你获得了,会被后来居上。也就是说你可能是先start()了,但是不一定能先run()。
使用继承thread的方式进行模拟卖票public class SoldTicketThread extends Thread { private int ticket = 5; private String name; // 构造方法 public SoldTicketThread(String name) { this.name = name; } public void run() { while (ticket > 0) { System.out.println(name + "卖出了一张票,剩余" + (--ticket) + "张票"); } } public static void main(String[] args) { // 创建三个线程,模拟三个窗口卖票 SoldTicketThread wd1 = new SoldTicketThread("窗口一"); SoldTicketThread wd2 = new SoldTicketThread("窗口二"); SoldTicketThread wd3 = new SoldTicketThread("窗口三"); // 启动者三个线程,也就是窗口开始卖票 wd1.start(); wd2.start(); wd3.start(); }}运行结果:(这是因为我们创建了3个线程,每个线程都有5张票的资源,所以每个线程都卖自己的5张票,无法实现资源共享)窗口二卖出了一张票,剩余4张票窗口一卖出了一张票,剩余4张票窗口一卖出了一张票,剩余3张票窗口一卖出了一张票,剩余2张票窗口一卖出了一张票,剩余1张票窗口一卖出了一张票,剩余0张票窗口二卖出了一张票,剩余3张票窗口二卖出了一张票,剩余2张票窗口二卖出了一张票,剩余1张票窗口二卖出了一张票,剩余0张票窗口三卖出了一张票,剩余4张票窗口三卖出了一张票,剩余3张票窗口三卖出了一张票,剩余2张票窗口三卖出了一张票,剩余1张票窗口三卖出了一张票,剩余0张票
综合上面的结果,我们只能创建一个线程,拿到这5张票的共享资源public class SoldTicketThread implements Runnable { private int ticket = 5; public void run() { while (ticket > 0) { System.out.println(Thread.currentThread().getName() + "卖出了一张票,剩余" + (--ticket) + "张票"); } } public static void main(String[] args) { // 创建一个实现了runnable接口的对象,拿到这5张票的资源 SoldTicketThread window = new SoldTicketThread(); //将这个资源类作为参数传递到3个线程中 Thread wd1=new Thread(window,"窗口一"); Thread wd2=new Thread(window,"窗口二"); Thread wd3=new Thread(window,"窗口三"); // 启动者三个线程,也就是窗口开始卖票 wd1.start(); wd2.start(); wd3.start(); }}运行结果:窗口一卖出了一张票,剩余4张票窗口一卖出了一张票,剩余2张票窗口一卖出了一张票,剩余1张票窗口二卖出了一张票,剩余3张票窗口一卖出了一张票,剩余0张票
如果你非要用继承thread的方式的话。。。public class SoldTicketThread extends Thread { private int ticket = 5; public void run() { while (ticket > 0) { System.out.println(Thread.currentThread().getName() + "卖出了一张票,剩余" + (--ticket) + "张票"); } } public static void main(String[] args) { SoldTicketThread window = new SoldTicketThread(); Thread wd1 = new Thread(window, "窗口二"); Thread wd2 = new Thread(window, "窗口一"); Thread wd3 = new Thread(window, "窗口三"); wd1.start(); wd2.start(); wd3.start(); }}运行结果:窗口随机,卖票顺序随机窗口二卖出了一张票,剩余4张票窗口二卖出了一张票,剩余1张票窗口二卖出了一张票,剩余0张票窗口三卖出了一张票,剩余2张票窗口一卖出了一张票,剩余3张票
好想让这个卖票有个顺序肿么破。。。,使用synchronized锁住卖票操作的整个内容,使一次只卖一次票。给我们的资源加把锁
采用实现Runnable接口实现:public class SoldTicketThread implements Runnable {private int ticket = 5;private synchronized void sale() {if (ticket > 0) {System.out.println(Thread.currentThread().getName() + "卖出了一张票,剩余"+ (--ticket) + "张票");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}public void run() {while (ticket > 0) {sale();// 这里要确保进入卖票环节前就把资源锁住}}public static void main(String[] args) {SoldTicketThread window = new SoldTicketThread();Thread wd1 = new Thread(window, "窗口二");Thread wd2 = new Thread(window, "窗口一");Thread wd3 = new Thread(window, "窗口三");wd1.start();wd2.start();wd3.start();}}运行结果:(线程间(窗口)会进行抢占cpu资源,是随机的)窗口三卖出了一张票,剩余4张票窗口一卖出了一张票,剩余3张票窗口二卖出了一张票,剩余2张票窗口一卖出了一张票,剩余1张票窗口一卖出了一张票,剩余0张票
继承Thread类public class SoldTicketThread extends Thread { private int ticket = 5; public synchronized void sale() { if (ticket > 0) { System.out.println(Thread.currentThread().getName() + "卖出了一张票,剩余" + (--ticket) + "张票"); } } public void run() { while (ticket > 0) { sale(); } } public static void main(String[] args) { SoldTicketThread window = new SoldTicketThread(); Thread wd1 = new Thread(window, "窗口二"); Thread wd2 = new Thread(window, "窗口一"); Thread wd3 = new Thread(window, "窗口三"); wd1.start(); wd2.start(); wd3.start(); }}运行结果:(窗口会进行抢占cpu资源,是随机的)窗口三卖出了一张票,剩余4张票窗口一卖出了一张票,剩余3张票窗口一卖出了一张票,剩余2张票窗口一卖出了一张票,剩余1张票窗口一卖出了一张票,剩余0张票
总结:因为我们只是创建了一个拥有5张票的线程类的对象(有5张火车票),然后把这个对象作为参数传递给3个新创建的thread对象,所以共享了这5张火车票。然后我们再卖票操作加了synchronized操作,就可以实现按顺序卖票了。
需要记住的点是,我觉得初学者老师会觉得程序是从上到下执行的,很符合我们的逻辑,但是线程可以看做是并发操作,并不是说你先start了,你就会先run。
还要记录的点事守护线程的点。。。在Dos环境下,jstack可以查看当前运行java类的pid,然后输入 jstack -l pid可以查看到目前有什么守护线程。。。。
- JAVA多线程之Thread&&Runnable
- Java多线程编程之Runnable、Thread简介
- Java多线程之 Thread VS Runnable
- JAVA多线程之Thread VS Runnable
- Java多线程 之 Runnable Thread (一)
- JAVA多线程之Runnable和Thread比较
- JAVA多线程之Runnable和Thread比较
- JAVA多线程:Thread、Runnable
- 多线程之Thread VS Runnable
- java多线程 Thread 和Runnable
- java 多线程(Thread,Runnable)
- java多线程 Thread 和Runnable
- java多线程Thread和Runnable
- Java多线程Thread与Runnable
- Java多线程--Runnable和Thread
- Java -- Thread 和 Runnable 多线程
- Java 中多线程的实现方法之Thread和Runnable
- Java多线程之 Thread VS Runnable 【带案例】
- 在VB.net中使用Entity Framework(vb.net EF6)
- CSS3的calc()使用
- javaWeb项目中的单例,多例,
- 关于Oracle中dbms_jobs的使用,异常:表或视图不存在
- 不可不知的 Android strings.xml 那些事
- JAVA多线程之Thread&&Runnable
- 软件项目版本号的命名规则及格式
- iOS—如何申请苹果公司开发者账号流程详细图文介绍(包括邓白氏编码的申请方法详细介绍)
- 栈实验之栈的基本操作
- spark的性能测试
- 磁力链接+爬虫
- poj3259 Wormholes
- JAVA不可变类(immutable)机制与String的不可变性
- @SuppressWarnings("serial")