26、Java入门—多线程之隋唐演义小案例
2016-11-01 11:46
519 查看
隋唐演义三个对象:
军队-ArmyRunnable;
英雄人物-KeyPersonThread;
舞台-Stage
//军队线程
//模拟作战双方行为
public class ArmyRunnable implements Runnable{
ArmyRunnable armyTaskOfSuiDynasty = new ArmyRunnable();
ArmyRunnable armyTaskOfarmyOfRevolt = new ArmyRunnable();
//使用Runnable 接口创建线程
Thread armyOfSuiDynasty = new Thread(armyTaskOfSuiDynasty,"隋军");
Thread armyOfRevolt = new Thread(armyTaskOfarmyOfRevolt,"农民起义军");
}
当线程并不是继承了Thread类而是实现了Runnable接口时,runnable中并没有getName()等方法,这时若想要调用这些方法就需要通过Thread类的静态方法currentThread()来获取当前线程的实体再调用。
在一个.java文件中能有多个类,但只能有一个public类(外部类)
为什么不调用run方法?
你可以理解为,run方法仅仅提供了业务逻辑,而线程运行是有更复杂要求的。这一切都封装在了Thread内部。所以记住一定不要自己调用run,而是调用start方法。
public class Actor extends Thread {
public void run() {
boolean running=true;
int count=0;
while(running){
System.out.println(getName()+"登台演出"+(++count));
if(count==50){
running=false;
}
if(count%10==0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread actor=new Actor();
actor.setName("Mr.Thread");
actor.start();
Thread actress=new Thread(new Actress(),"Ms.Runnable");
actress.start();
}
}
class Actress implements Runnable{
public void run() {
boolean running=true;
int count=0;
while(running){
System.out.println(Thread.currentThread().getName()+"登台演出"+(count++));
if(count==50){
running=false;
}
if(count%10==0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
此处++count若改成count++ 结果是 0-9 10-19......90-99 结束
1:创建线程的方法有两种<br>
1-1:继承Thread类<br>
1-2:实现Runnable接口<br>
2:线程中的方法比较有特点,比如:启动(start)、休眠(sleep)、停止等,多个线程是交互执行的(CUP在某个时刻
只能执行一个线程,当一个线程休眠了或者执行完毕了,另一个线程才能占用CPU来执行),因为这是CPU的结构来决
定的,在某个时刻CUP只能执行一个线程,不过速度相当快,对于人来讲可以认为是并行执行的。
在一个.java文件中,可以有多个类,但只能有一个public类。
这两种创建线程的方法本身没有什么不同,一个是实现Runnable接口,一个是继承Thread类。而使用实现Runnable接口这种方法:1.可以避免Java的单继承的特性带来的局限性;2.适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码及数据有效分离,较好地体现了面向对象的设计思想。开发中大多情况下都使用实现Runnable接口这种方法创建线程。
实现Runnable接口创建的线程最终还是要通过将自身实例作为参数传递给Thread然后执行
语法:Thread Actress = new Thread(Runnable target, String name)
例如:Thread actressThread=new Thread(new Actress(),"Ms.Runnable");
actressThread.start();
}
}
volatile关键字
保证了线程可以正确地读取其他线程写入的值,如果不写成volatile,由于可见性的问题,当前线程有可能不能读到这个值。
可见性JMM(JAVA内存模型)happens-before原则、可见性原则
用volatile修饰的变量,线程在每次使用该变量的时候,都会读取变量修改后的值
加入join是为了让舞台线程最后停止,如果不加有可能舞台线程结束,军队线程还未停止,就好比导演喊停,演员还在演!可以在join后面加入测试语句System.out.println("舞台结束!");,然后去掉或者保留join观察效果。
Thread.yield();//让出处理器时间,公平竞争
军队线程
public class armyRunnable implements Runnable {
//volatile保证了线程可以正确读取其他线程写入的值
volatile boolean keeprunning=true;
public void run() {
while(keeprunning){
//发动五连击
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"攻击对方 ["+i+"]");
//释放资源
Thread.yield();
}
}
System.out.println(Thread.currentThread().getName()+"结束战斗");
}
}
//舞台线程
public class Stage extends Thread {
public void run(){
//创建runnable接口实例
ArmyRunnable armyTaskOfSuiDynasty = new ArmyRunnable();
ArmyRunnable armyTaskOfRevolt = new ArmyRunnable();
//使用Runnable接口创建线程
Thread armyOfSuiDynasty = new Thread(armyTaskOfSuiDynasty,"隋军");
Thread armyOfRevolt = new Thread(armyTaskOfRevolt,"农民起义军");
//启动线程,让军队开始作战
armyOfSuiDynasty.start();
armyOfRevolt.start();
//舞台线程休眠,大家专心观看军队厮杀
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//停止军队线程
armyTaskOfSuiDynasty.keepRunning = false;
armyTaskOfRevolt.keepRunning = false;
//舞台线程等待该线程的结束
try {
armyOfRevolt.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
keyperson类
public class Keyperson extends Thread {
public void run(){
System.out.println(getName()+"开始战斗");
for(int i=0;i<10;i++){
System.out.println(getName()+"左突右击,攻击隋军");
}
System.out.println(getName()+"结束战斗");
}
}
join方法会是所有线程等待调用join方法的线程执行完毕
/**
*隋唐演义大舞台
*/
public class Stage extends Thread {
@Override
public void run() {
System.out.println("正当双方杀得正High,半路杀出了个程咬金!");
Thread mrChen=new KeyPersonThread();
mrChen.setName("程咬金");
//停止军队作战
//停止线程的方法
armyTaskOfSuiDynasty.keepRunning=false;
armyTaskOfRevolt.keepRunning=false;
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
/**
* 历史大戏留给关键人物
*/
mrChen.start();
//万众瞩目,所有线程等待程先生完成历史使命
try {
mrChen.join();//对象是mrChen
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println("谢谢观看隋唐演义,再见!");
}
Ps:Thread.currentThread()表示静态意思。
军队-ArmyRunnable;
英雄人物-KeyPersonThread;
舞台-Stage
//军队线程
//模拟作战双方行为
public class ArmyRunnable implements Runnable{
ArmyRunnable armyTaskOfSuiDynasty = new ArmyRunnable();
ArmyRunnable armyTaskOfarmyOfRevolt = new ArmyRunnable();
//使用Runnable 接口创建线程
Thread armyOfSuiDynasty = new Thread(armyTaskOfSuiDynasty,"隋军");
Thread armyOfRevolt = new Thread(armyTaskOfarmyOfRevolt,"农民起义军");
}
当线程并不是继承了Thread类而是实现了Runnable接口时,runnable中并没有getName()等方法,这时若想要调用这些方法就需要通过Thread类的静态方法currentThread()来获取当前线程的实体再调用。
在一个.java文件中能有多个类,但只能有一个public类(外部类)
为什么不调用run方法?
你可以理解为,run方法仅仅提供了业务逻辑,而线程运行是有更复杂要求的。这一切都封装在了Thread内部。所以记住一定不要自己调用run,而是调用start方法。
public class Actor extends Thread {
public void run() {
boolean running=true;
int count=0;
while(running){
System.out.println(getName()+"登台演出"+(++count));
if(count==50){
running=false;
}
if(count%10==0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread actor=new Actor();
actor.setName("Mr.Thread");
actor.start();
Thread actress=new Thread(new Actress(),"Ms.Runnable");
actress.start();
}
}
class Actress implements Runnable{
public void run() {
boolean running=true;
int count=0;
while(running){
System.out.println(Thread.currentThread().getName()+"登台演出"+(count++));
if(count==50){
running=false;
}
if(count%10==0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
此处++count若改成count++ 结果是 0-9 10-19......90-99 结束
1:创建线程的方法有两种<br>
1-1:继承Thread类<br>
1-2:实现Runnable接口<br>
2:线程中的方法比较有特点,比如:启动(start)、休眠(sleep)、停止等,多个线程是交互执行的(CUP在某个时刻
只能执行一个线程,当一个线程休眠了或者执行完毕了,另一个线程才能占用CPU来执行),因为这是CPU的结构来决
定的,在某个时刻CUP只能执行一个线程,不过速度相当快,对于人来讲可以认为是并行执行的。
在一个.java文件中,可以有多个类,但只能有一个public类。
这两种创建线程的方法本身没有什么不同,一个是实现Runnable接口,一个是继承Thread类。而使用实现Runnable接口这种方法:1.可以避免Java的单继承的特性带来的局限性;2.适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码及数据有效分离,较好地体现了面向对象的设计思想。开发中大多情况下都使用实现Runnable接口这种方法创建线程。
实现Runnable接口创建的线程最终还是要通过将自身实例作为参数传递给Thread然后执行
语法:Thread Actress = new Thread(Runnable target, String name)
例如:Thread actressThread=new Thread(new Actress(),"Ms.Runnable");
actressThread.start();
}
}
volatile关键字
保证了线程可以正确地读取其他线程写入的值,如果不写成volatile,由于可见性的问题,当前线程有可能不能读到这个值。
可见性JMM(JAVA内存模型)happens-before原则、可见性原则
用volatile修饰的变量,线程在每次使用该变量的时候,都会读取变量修改后的值
加入join是为了让舞台线程最后停止,如果不加有可能舞台线程结束,军队线程还未停止,就好比导演喊停,演员还在演!可以在join后面加入测试语句System.out.println("舞台结束!");,然后去掉或者保留join观察效果。
Thread.yield();//让出处理器时间,公平竞争
军队线程
public class armyRunnable implements Runnable {
//volatile保证了线程可以正确读取其他线程写入的值
volatile boolean keeprunning=true;
public void run() {
while(keeprunning){
//发动五连击
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"攻击对方 ["+i+"]");
//释放资源
Thread.yield();
}
}
System.out.println(Thread.currentThread().getName()+"结束战斗");
}
}
//舞台线程
public class Stage extends Thread {
public void run(){
//创建runnable接口实例
ArmyRunnable armyTaskOfSuiDynasty = new ArmyRunnable();
ArmyRunnable armyTaskOfRevolt = new ArmyRunnable();
//使用Runnable接口创建线程
Thread armyOfSuiDynasty = new Thread(armyTaskOfSuiDynasty,"隋军");
Thread armyOfRevolt = new Thread(armyTaskOfRevolt,"农民起义军");
//启动线程,让军队开始作战
armyOfSuiDynasty.start();
armyOfRevolt.start();
//舞台线程休眠,大家专心观看军队厮杀
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//停止军队线程
armyTaskOfSuiDynasty.keepRunning = false;
armyTaskOfRevolt.keepRunning = false;
//舞台线程等待该线程的结束
try {
armyOfRevolt.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
keyperson类
public class Keyperson extends Thread {
public void run(){
System.out.println(getName()+"开始战斗");
for(int i=0;i<10;i++){
System.out.println(getName()+"左突右击,攻击隋军");
}
System.out.println(getName()+"结束战斗");
}
}
join方法会是所有线程等待调用join方法的线程执行完毕
/**
*隋唐演义大舞台
*/
public class Stage extends Thread {
@Override
public void run() {
System.out.println("正当双方杀得正High,半路杀出了个程咬金!");
Thread mrChen=new KeyPersonThread();
mrChen.setName("程咬金");
//停止军队作战
//停止线程的方法
armyTaskOfSuiDynasty.keepRunning=false;
armyTaskOfRevolt.keepRunning=false;
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
/**
* 历史大戏留给关键人物
*/
mrChen.start();
//万众瞩目,所有线程等待程先生完成历史使命
try {
mrChen.join();//对象是mrChen
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println("谢谢观看隋唐演义,再见!");
}
Ps:Thread.currentThread()表示静态意思。
相关文章推荐
- java多线程简单案例入门
- java中的Java5.0 的注释 (Annotation)、多线程包2(J2SE入门26)
- 1 Java 多线程入门大全(适用于有一定基础者)
- Java多线程入门
- java 多线程 入门 线程生命周期图
- 线程进程【重磅出击】 java入门到精通——多线程(上)
- 【重磅出击】 java入门到精通——多线程(上)
- Java 多线程入门大全(适用于有一定基础者)
- java 多线程 synchronized 入门博文二
- Java多线程入门
- Java5 多线程(一)--入门篇
- Java语言入门 -- 第七章 Java的多线程
- Java多线程程序设计入门-Java基础-Java-编程开发
- Java 多线程入门大全(适用于有一定基础者)
- java案例开发集锦之io流与多线程的文件删除
- Java多线程程序设计入门
- 案例4-3 Ajax的响应处理简单实例(征服Ajax——Web 2.0快速入门与项目实践Java)
- [零基础学JAVA]Java SE应用部分-26.多线程(04) 推荐
- 黑马程序员——Java多线程入门
- java 多线程 例子 入门博文一