博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程(一)
阅读量:5316 次
发布时间:2019-06-14

本文共 6508 字,大约阅读时间需要 21 分钟。

synchronized关键字实现多线程的3种方式:

1. 继承Thread类
2. 实现Runnable接口
3. 匿名类的方式
注: 启动线程是start()方法,run()并不能启动一个新的线程

 

一.继承线程类

使用多线程,就可以做到盖伦在攻击提莫的同时,赏金猎人也在攻击盲僧 

设计一个类KillThread 继承Thread,并且重写run方法 
启动线程办法: 实例化一个KillThread对象,并且调用其start方法 
就可以观察到 赏金猎人攻击盲僧的同时,盖伦也在攻击提莫

package multiplethread; import charactor.Hero; public class KillThread extends Thread{         private Hero h1;    private Hero h2;     public KillThread(Hero h1, Hero h2){        this.h1 = h1;        this.h2 = h2;    }     public void run(){        while(!h2.isDead()){            h1.attackHero(h2);        }    }}
KillThread.java
package multiplethread; import charactor.Hero; public class TestThread {     public static void main(String[] args) {                 Hero gareen = new Hero();        gareen.name = "盖伦";        gareen.hp = 616;        gareen.damage = 50;         Hero teemo = new Hero();        teemo.name = "提莫";        teemo.hp = 300;        teemo.damage = 30;                 Hero bh = new Hero();        bh.name = "赏金猎人";        bh.hp = 500;        bh.damage = 65;                 Hero leesin = new Hero();        leesin.name = "盲僧";        leesin.hp = 455;        leesin.damage = 80;                 KillThread killThread1 = new KillThread(gareen,teemo);        killThread1.start();        KillThread killThread2 = new KillThread(bh,leesin);        killThread2.start();             }     }
TestThread

 

二.实现Runnable接口

创建类Battle,实现Runnable接口

启动的时候,首先创建一个Battle对象,然后再根据该battle对象创建一个线程对象,并启动

package multiplethread; import charactor.Hero; public class Battle implements Runnable{         private Hero h1;    private Hero h2;     public Battle(Hero h1, Hero h2){        this.h1 = h1;        this.h2 = h2;    }     public void run(){        while(!h2.isDead()){            h1.attackHero(h2);        }    }}
Battle.java
package multiplethread; import charactor.Hero; public class TestThread {     public static void main(String[] args) {                 Hero gareen = new Hero();        gareen.name = "盖伦";        gareen.hp = 616;        gareen.damage = 50;         Hero teemo = new Hero();        teemo.name = "提莫";        teemo.hp = 300;        teemo.damage = 30;                 Hero bh = new Hero();        bh.name = "赏金猎人";        bh.hp = 500;        bh.damage = 65;                 Hero leesin = new Hero();        leesin.name = "盲僧";        leesin.hp = 455;        leesin.damage = 80;                 Battle battle1 = new Battle(gareen,teemo);                 new Thread(battle1).start();         Battle battle2 = new Battle(bh,leesin);        new Thread(battle2).start();     }     }
TestThread

 

三.匿名类

使用匿名类,继承Thread,重写run方法,直接在run方法中写业务代码
匿名类的一个好处是可以很方便的访问外部的局部变量。
前提是外部的局部变量需要被声明为final。(JDK7以后就不需要了)
 
package multiplethread;  import charactor.Hero;  public class TestThread {      public static void main(String[] args) {                  Hero gareen = new Hero();        gareen.name = "盖伦";        gareen.hp = 616;        gareen.damage = 50;          Hero teemo = new Hero();        teemo.name = "提莫";        teemo.hp = 300;        teemo.damage = 30;                  Hero bh = new Hero();        bh.name = "赏金猎人";        bh.hp = 500;        bh.damage = 65;                  Hero leesin = new Hero();        leesin.name = "盲僧";        leesin.hp = 455;        leesin.damage = 80;                  //匿名类        Thread t1= new Thread(){            public void run(){                //匿名类中用到外部的局部变量teemo,必须把teemo声明为final                //但是在JDK7以后,就不是必须加final的了                while(!teemo.isDead()){                    gareen.attackHero(teemo);                }                          }        };                 t1.start();                  Thread t2= new Thread(){            public void run(){                while(!leesin.isDead()){                    bh.attackHero(leesin);                }                          }        };        t2.start();             }      }
TestThread.java

 

四.常见线程方法:

 

五.Concurrency 问题(并发性):

 

package multiplethread;  import java.text.SimpleDateFormat;import java.util.Date;   public class TestThread {         public static String now(){        return new SimpleDateFormat("HH:mm:ss").format(new Date());    }         public static void main(String[] args) {        final Object someObject = new Object();                  Thread t1 = new Thread(){            public void run(){                try {                    System.out.println( now()+" t1 线程已经运行");                    System.out.println( now()+this.getName()+ " 试图占有对象:someObject");                    synchronized (someObject) {                                                  System.out.println( now()+this.getName()+ " 占有对象:someObject");                        Thread.sleep(5000);                        System.out.println( now()+this.getName()+ " 释放对象:someObject");                    }                    System.out.println(now()+" t1 线程结束");                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        };        t1.setName(" t1");        t1.start();        Thread t2 = new Thread(){              public void run(){                try {                    System.out.println( now()+" t2 线程已经运行");                    System.out.println( now()+this.getName()+ " 试图占有对象:someObject");                    synchronized (someObject) {                        System.out.println( now()+this.getName()+ " 占有对象:someObject");                        Thread.sleep(5000);                        System.out.println( now()+this.getName()+ " 释放对象:someObject");                    }                    System.out.println(now()+" t2 线程结束");                } catch (InterruptedException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        };        t2.setName(" t2");        t2.start();    }       }
TestThread.java
17:00:34 t2 线程已经运行17:00:34 t1 线程已经运行17:00:34 t2 试图占有对象:someObject17:00:34 t1 试图占有对象:someObject17:00:34 t2 占有对象:someObject17:00:39 t2 释放对象:someObject17:00:39 t2 线程结束17:00:39 t1 占有对象:someObject17:00:44 t1 释放对象:someObject17:00:44 t1 线程结束

 

在recover前,直接加上synchronized ,其所对应的同步对象,就是this

和hurt方法达到的效果是一样
外部线程访问gareen的方法,就不需要额外使用synchronized 了

//回血    //直接在方法前加上修饰符synchronized    //其所对应的同步对象,就是this    //和hurt方法达到的效果一样    public synchronized void recover(){        hp=hp+1;    }         //掉血    public void hurt(){        //使用this作为同步对象        synchronized (this) {            hp=hp-1;           }    }

 

转载于:https://www.cnblogs.com/exciting/p/10705661.html

你可能感兴趣的文章
内存地址对齐
查看>>
JavaScript介绍
查看>>
yum 命令跳过特定(指定)软件包升级方法
查看>>
创新课程管理系统数据库设计心得
查看>>
Could not resolve view with name '***' in servlet with name 'dispatcher'
查看>>
pandas 修改指定列中所有内容
查看>>
lua语言入门之Sublime Text设置lua的Build System
查看>>
vue.js基础
查看>>
电脑的自带图标的显示
查看>>
[转载] redis 的两种持久化方式及原理
查看>>
C++ 删除字符串的两种实现方式
查看>>
ORA-01502: 索引'P_ABCD.PK_WEB_BASE'或这类索引的分区处于不可用状态
查看>>
Java抽象类和接口的比较
查看>>
MyBaits学习
查看>>
管道,数据共享,进程池
查看>>
CSS
查看>>
[LeetCode] 55. Jump Game_ Medium tag: Dynamic Programming
查看>>
[Cypress] Stub a Post Request for Successful Form Submission with Cypress
查看>>
程序集的混淆及签名
查看>>
判断9X9数组是否是数独的java代码
查看>>