多线程基础1-线程2种方式、2方式实现购票、join、yield
来源:互联网 发布:java金融开源项目 编辑:程序博客网 时间:2024/06/06 21:38
- 继承Thread创建线程
- 实现Runnable创建线程
- 继承Thread实现购票
- 实现Runnable实现购票
继承Thread创建线程
package safly;/* * Thread的常用方法: * 1.start():启动线程并执行相应的run()方法 * 2.run():子线程要执行的代码放入run()方法中 * 3.currentThread():静态的,调取当前的线程 * 4.getName():获取此线程的名字 * 5.setName():设置此线程的名字 * 6.yield():调用此方法的线程释放当前CPU的执行权 * 7.join():在A线程中调用B线程的join()方法,表示:当执行到此方法,A线程停止执行,直至B线程执行完毕, * A线程再接着join()之后的代码执行 * 8.isAlive():判断当前线程是否还存活 * 9.sleep(long l):显式的让当前线程睡眠l毫秒 * 10.线程通信:wait() notify() notifyAll() * * 设置线程的优先级 * getPriority() :返回线程优先值 setPriority(int newPriority) :改变线程的优先级 */class SubThread extends Thread { public void run() { for (int i = 1; i <= 10; i++) { System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().getPriority() + ":" + i); } }}public class Demo { public static void main(String[] args) { SubThread st1 = new SubThread(); st1.setName("子线程1"); st1.start(); Thread.currentThread().setName("========主线程"); for (int i = 1; i <= 10; i++) { System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().getPriority() + ":" + i); if(i % 2 == 0){ Thread.currentThread().yield(); } if(i == 7){ try { st1.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } System.out.println(st1.isAlive()); }}
========主线程:5:1子线程1:5:1========主线程:5:2子线程1:5:2========主线程:5:3子线程1:5:3========主线程:5:4子线程1:5:4子线程1:5:5========主线程:5:5========主线程:5:6子线程1:5:6========主线程:5:7子线程1:5:7子线程1:5:8子线程1:5:9子线程1:5:10========主线程:5:8========主线程:5:9========主线程:5:10false
主线程在执行到i=7时候,如果子线程任务没有执行完毕,那么子线程join进来,执行完毕子线程代码,在继续执行主线程代码,所以子线程执行任务完毕之后,才执行主线程i=8的操作
因为主线程在i=2时候,交出执行权限,然后主线程、子线程继续抢夺cpu执行权限,上面的例子就是主线程yield交出cpu执行权限,由子线程抢夺
下面的例子就是主线程在yield交出cpu执行权限,再次有主线程获取
或者如下的效果
========主线程:5:1========主线程:5:2========主线程:5:3========主线程:5:4子线程1:5:1子线程1:5:2子线程1:5:3子线程1:5:4========主线程:5:5子线程1:5:5子线程1:5:6子线程1:5:7子线程1:5:8子线程1:5:9子线程1:5:10========主线程:5:6========主线程:5:7========主线程:5:8========主线程:5:9========主线程:5:10false
实现Runnable创建线程
package safly;/* * 创建多线程的方式二:通过实现的方式 * * 对比一下继承的方式 vs 实现的方式 * 1.联系:public class Thread implements Runnable * 2.哪个方式好?实现的方式优于继承的方式 * why? ① 避免了java单继承的局限性 * ② 如果多个线程要操作同一份资源(或数据),更适合使用实现的方式 *///1.创建一个实现了Runnable接口的类class PrintNum1 implements Runnable { //2.实现接口的抽象方法 public void run() { // 子线程执行的代码 for (int i = 1; i <= 10; i++) { if (i % 2 == 0) { System.out.println(Thread.currentThread().getName() + ":" + i); } } }}public class Demo { public static void main(String[] args) { //3.创建一个Runnable接口实现类的对象 PrintNum1 p = new PrintNum1(); //要想启动一个多线程,必须调用start() //4.将此对象作为形参传递给Thread类的构造器中,创建Thread类的对象,此对象即为一个线程 Thread t1 = new Thread(p); //5.调用start()方法:启动线程并执行run() t1.start();//启动线程;执行Thread对象生成时构造器形参的对象的run()方法。 //再创建一个线程 Thread t2 = new Thread(p); t2.start(); }}
输出如下:
Thread-0:2Thread-1:2Thread-0:4Thread-1:4Thread-0:6Thread-1:6Thread-0:8Thread-0:10Thread-1:8Thread-1:10
继承Thread实现购票
package safly;//模拟火车站售票窗口,开启三个窗口售票,总票数为100张//存在线程的安全问题class Window extends Thread { static int ticket = 10; public void run() { while (true) { if (ticket > 0) { System.out.println(Thread.currentThread().getName() + "售票,票号为:" + ticket--); } else { break; } } }}public class Demo { public static void main(String[] args) { Window w1 = new Window(); Window w2 = new Window(); Window w3 = new Window(); w1.setName("窗口1"); w2.setName("窗口2"); w3.setName("窗口3"); w1.start(); w2.start(); w3.start(); }}
需要注意的是在run方法中,使用共享的静态变量,这个方法其实也不能完全解决数据共享的问题,因为可能某一个线程拿到火车票了,例如票号10,然后去执行–操作,在这个–操作还没执行完,另外一个线程也拿到共享数据了,此刻依然是没有进行减少操作完毕之前的10,所以就造成如下的结果,打印重票错票
窗口3售票,票号为:10窗口2售票,票号为:9窗口1售票,票号为:10窗口2售票,票号为:7窗口3售票,票号为:8窗口2售票,票号为:5窗口1售票,票号为:6窗口1售票,票号为:2窗口2售票,票号为:3窗口3售票,票号为:4窗口1售票,票号为:1
如果改成int ticket = 10;就是开了3个线程,每个线程有自己的变量,而非static共享的变量,所以每个线程会输出10长票
看看是如何输出的
窗口3售票,票号为:10窗口2售票,票号为:10窗口1售票,票号为:10窗口2售票,票号为:9窗口3售票,票号为:9窗口2售票,票号为:8窗口1售票,票号为:9窗口2售票,票号为:7窗口2售票,票号为:6窗口3售票,票号为:8窗口2售票,票号为:5窗口2售票,票号为:4窗口3售票,票号为:7窗口3售票,票号为:6窗口3售票,票号为:5窗口3售票,票号为:4窗口1售票,票号为:8窗口1售票,票号为:7窗口1售票,票号为:6窗口3售票,票号为:3窗口2售票,票号为:3窗口3售票,票号为:2窗口1售票,票号为:5窗口3售票,票号为:1窗口2售票,票号为:2窗口2售票,票号为:1窗口1售票,票号为:4窗口1售票,票号为:3窗口1售票,票号为:2窗口1售票,票号为:1
实现Runnable实现购票
package safly;//使用实现Runnable接口的方式,售票/* * 此程序存在线程的安全问题:打印车票时,会出现重票、错票 */class Window1 implements Runnable { static int ticket = 10; //int也可以// int ticket = 10; public void run() { while (true) { if (ticket > 0) { System.out.println(Thread.currentThread().getName() + "售票,票号为:" + ticket--); } else { break; } } }}public class Demo { public static void main(String[] args) { Window1 w = new Window1(); Thread t1 = new Thread(w); Thread t2 = new Thread(w); Thread t3 = new Thread(w); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t1.start(); t2.start(); t3.start(); }}
利用实现的方式实现购票,同理一样,但是static int ticket = 10;跟int ticket = 10;写法都行,但是都会出现重票错票
输出如下:
窗口1售票,票号为:10窗口3售票,票号为:9窗口3售票,票号为:7窗口2售票,票号为:9窗口3售票,票号为:6窗口3售票,票号为:4窗口1售票,票号为:8窗口3售票,票号为:3窗口3售票,票号为:1窗口2售票,票号为:5窗口1售票,票号为:2
阅读全文
0 0
- 多线程基础1-线程2种方式、2方式实现购票、join、yield
- java多线程基础(5)-调度方式之暂停当前线程方式4-连接线程(join)
- 09-多线程(创建线程的第二种方式—实现Runnable接口)1 2 10-多线程(第二种方式的细节) 11-多线程(第二种方式的好处)
- java多线程基础(2)-调度方式之暂停当前线程方式1-阻塞
- CountDownLatch和join两种方式实现多线程并行处理
- java 多线程(2) 线程的调度和优先级 / sleep() / interrupt() 打断join() / yield() / setPriority()
- Java多线程-线程状态、sleep()、yield()、join()
- java多线程基础(3)-调度方式之暂停当前线程方式2-放弃
- android 基础 线程sleep,join,yield
- java 线程 --- join,sleep,yield 基础学习
- 多线程的2种实现方式
- 线程的2种实现方式
- 线程的2种实现方式
- 2、线程实现的两种方式
- Java基础:多线程之线程创建的两种方式
- 【Java多线程】实现java线程的两种方式
- Java多线程:创建线程的两种实现方式
- 线程池(实现多线程的第三种方式)
- 无名飞控的姿态解算和控制(二)
- 蔚来ES8正式上市;贾跃亭以老赖身份登纽约时报;SpaceX首次利用回收火箭执行任务丨价值早报
- 安卓Android--L2TP教程
- C++实现线程安全的单例模式
- RNN以及LSTM的介绍和公式梳理
- 多线程基础1-线程2种方式、2方式实现购票、join、yield
- 《JAVA编程技巧1001条》第338条:数学函数 TAN
- 前端开发面试题总结
- 关于spring
- [leetcode] 6. ZigZag Conversion
- 美国税改法案修订会如何影响加密货币投资者
- IOTA澄清未与微软正式合作,价格随之下跌15%
- UDP协议之不可靠性
- CBOE比特币期货成交量忽高忽低