java基础知识回顾之java Thread类学习(三)--java线程实现常见的两种方式实现好处:
2023-09-14 08:57:14 时间
总结:实现Runnable接口比继承Thread类更有优势:
1.因为java只能单继承,实现Runnable接口可以避免单继承的局限性
2.继承Thread类,多个线程不能处理或者共享同一个资源,但是实现Runnable接口可以处理同一个资源。
下面我们做个测试:验证下。车站的售票系统售票的例子,车站的各个售票口相当于各个线程,我们先使用第一种方法几继承Thread类的方式实现:
代码如下:
package com.lp.ecjtu.Thread; /** * * @author Administrator * 车站的售票系统售票的例子,车站的各个售票口相当于各个线程。 * */ public class TicketsThread extends Thread{ //用静态变量存放这100张票,这样就不会卖重复 private int tickets = 100; public void run(){ while(true){ if(tickets > 0){ System.out.println(Thread.currentThread().getName()+"***sale***"+(--tickets)); } } } /** * @param args */ public static void main(String[] args) { // 不合理的买票程序,因为,不同线程都可以卖同一张票, //现实生活中不是这样的,窗口1买完第99张票,窗口2不可以卖了。 TicketsThread t1 = new TicketsThread(); TicketsThread t2 = new TicketsThread(); TicketsThread t3 = new TicketsThread(); t1.start(); t2.start(); t3.start(); } }
代码的原理图如下:
总结:不合理的卖票方法,不同线程都可以卖同一张票,现实生活中不是这样的,窗口1卖完99号票,窗口2就不可以再卖这张票了。
怎么解决呢?使用实现Runnable接口的方法就可以解决,代码如下:
public class TicketsRunnable implements Runnable { private int ticket=100; //Object obj = new Object(); public TicketsRunnable(){ System.out.println("*****************************"); } @Override public void run() { // TODO Auto-generated method stub while(true){ //synchronized(obj){ //同步代码块 if(ticket > 0){//当线程0被调起的时候,当执行到这条判断语句的时候,线程1被调起抢了CPU资源,线程0进入冻结状态。 try { Thread.sleep(100);//中断当前活跃的线程,或者执行的线程 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"正在卖票"+ticket--); //System.out.println(Thread.currentThread().getId()); //System.out.println(Thread.currentThread().getName()); } //} } } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub TicketsRunnable runna = new TicketsRunnable(); Thread t1 = new Thread(runna); Thread t2 = new Thread(runna); Thread t3 = new Thread(runna); t1.start(); t2.start(); t3.start(); } }
上面代码简单内存图理解如下:
总结:三个窗口再卖100张票,直到卖完,3个线程才停止。卖的票的号码没有重复,真正实现了现实生活中的卖票的效果。但是存在一个线程安全问题,通过测试运行发现,打印出了0,-1,-2等错票,多线程运行出现了安全问题,这就需要引入线程锁机制,下一篇博客详细的讲解怎样避免这一问题。
相关文章
- java -version 问题 : C:ProgramDataOracleJavajavapath;
- java基础知识回顾之javaIO类---BufferedReader和BufferedWriter
- java基础知识回顾之java Thread类--java线程实现常见的两种方式实现Runnable接口(二)
- 你必须知道的Java基础知识
- 基础知识《零》---Java程序运行机制及运行过程
- 基础知识《十四》Java异常的栈轨迹fillInStackTrace和printStackTrace的用法
- JAVA学习(三):Java基础语法(变量、常量、数据类型、运算符与数据类型转换)
- Java实现填符号凑算式
- Java实现 蓝桥杯 历届真题 稍大的串
- Java 蓝桥杯 算法训练 字符串的展开 (JAVA语言实现)
- Aliyun Java Initializr 和 Spring 官方的到底有什么区别?
- Gradle在大型Java项目上的应用
- Java的字节码和ABAP load的比较
- 华为OD机试 - 最少面试官数(Java & JS & Python)
- Java扑克牌(斗地主发牌)
- 【Java】java中javaSE与javaEE的区别
- Java 8 中的 java.util.Map#computeIfAbsent
- java 程序运行的基础知识【Java bytecode】
- 下载各个版本java (Java Development Kit)
- 【JAVA面试必会】JMM高并发详解(java内存模型、JMM三大特征、volatile关键字 )
- 用eclipse中打开Java项目
- JAVA开发讲义(二)-Java程序设计之数据之谜二