java之多线程

多线程即在同一时间,可以做多件事情。

线程的创建和启动

方法一:继承Thread类创建线程类

1.创建一个类,并继承Thread类,重写run方法,该run方法就是线程执行体
2.创建类的实例
3.调用该实例的start()方法

注意:
用这种方法创建的线程类的全局变量是不会共享的;
类的Main方法是一个主线程;
用户启动的多个线程的名字默认依次为Thread-1,Thread-2…Thread-n

public class scanner extends Thread
{
   
    public  void run()
    {
        //线程执行体
        ------获取当前线程可以直接用this.getName(),this可以省去
    }

    public static void main(String[] args) {
        new scanner().start();------创建第一个线程
        new scanner().start();-------创建第二个线程
    }
}

方法二:实现Runnable接口创建线程类

1.定义Runnable接口的实现类,并重写该接口的run方法
2.创建Runnable实现类的实例,并一此实例作为Thread的target来创建线程对象
3.调用线程对象的start()方法来启动该线程

注意:用该方法创建的线程,可以共享线程类的全局变量

public class scanner implements Runnable
{

    public  void run()
    {
        //线程执行体
        ------获取当前线程用Thread.currentThread().getName();
        ------和方法一比较会复杂些
    }

    public static void main(String[] args) {
        scanner scanner = new scanner();
        new Thread(scanner,"线程名字").start();//创建线程一
        new Thread(scanner,"线程名字").start();//创建线程二
    }
}

方法三:匿名类

  //匿名类
        Thread t1= new Thread(){
            public void run(){
                ----匿名类中用到外部的局部变量teemo,必须把teemo声明为final
                -----但是在JDK7以后,就不是必须加final的了
                while(!teemo.isDead()){
                    gareen.attackHero(teemo);
                }              
            }
        };
         
        t1.start();

常用方法

  • sleep(毫秒) 当前线程暂停
  • join() 加入到当前线程中
  • setPriority() 线程优先级
  • yield() 临时暂停
  • setDaemon() 守护线程
  • currentThread() 获取当前线程
  • getName(): 获取当前线程的名字
  • setName(): 设置当前线程的名字

join线程

当某个程序执行流中调用其它线程的join()方法时,调用线程将被阻塞,直到join线程执行完

在for循环外面时是主线程和Thread-1在并发执行,到了for循环中,Thread-2使用了join方法,也就导致主线程必须等待Thread-2执行结束才会继续执行

  • join():等待被join的线程执行完成
  • join(long millis):等待被join的线程的时间最长为millis毫秒,如果在millis毫秒内被join的线程还没有执行结束,则不在等待
 public static void main(String[] args) throws InterruptedException {

        new Thread().start();------创建第一个线程
        for(int i =0;i<100;i++)
        {
            if(i==20)
            {
                scanner scanner = new scanner();
                scanner.start();-------创建第二个线程
                scanner.join();------join线程
            }
        }


    }
public class TestThread {
 
   public static void main(String[] args) {
         
       final Hero gareen = new Hero();
       gareen.name = "盖伦";
       gareen.hp = 616;
       gareen.damage = 50;
 
       final Hero teemo = new Hero();
       teemo.name = "提莫";
       teemo.hp = 300;
       teemo.damage = 30;
         
       final Hero bh = new Hero();
       bh.name = "赏金猎人";
       bh.hp = 500;
       bh.damage = 65;
         
       final Hero leesin = new Hero();
       leesin.name = "盲僧";
       leesin.hp = 455;
       leesin.damage = 80;
         
       Thread t1= new Thread(){
           public void run(){
               while(!teemo.isDead()){
                   gareen.attackHero(teemo);
               }              
           }
       };
         
       t1.start();

       ---代码执行到这里,一直是main线程在运行
       try {
          ---t1线程加入到main线程中来,只有t1线程运行结束,才会继续往下走
           t1.join();
       } catch (InterruptedException e) {
          ---- TODO Auto-generated catch block
           e.printStackTrace();
       }

       Thread t2= new Thread(){
           public void run(){
               while(!leesin.isDead()){
                   bh.attackHero(leesin);
               }              
           }
       };
      -----会观察到盖伦把提莫杀掉后,才运行t2线程
       t2.start();
         
   }
     
}

后台线程

后台线程:是指在后台运行,为其它线程提供给服务的线程,又称为“守护线程”。

后台线程的特征:如果所有的前台线程都死亡,后台线程会自动死亡

  • setDaemon(true):将指定线程设置成后台线程

setDaemon(true)必须在start()之前使用

线程睡眠

*static sleep(long millis):将使当前正在执行的线程暂停millis毫秒,将使线程进入阻塞状态

线程让步:yieId

  • yieId():也是Thread的一个静态方法,他会让当前正在执行的线程暂停一下,但它不会阻塞该线程,而是将该线程转入就绪状态

yieId()与sleep()的区别:
1.sleep暂停后会其它线程执行机会,不会理会其它线程的优先级,但是yieId只会给优先级相同或更高的线程执行机会
2.sleep方法比yieId方法更具有好的可移植性,通常不建议使用yieId()方法来控制并发的执行

改变线程的优先级

每个线程执行时都有一个优先级,优先级越高被执行的概率就越大,而优先级越低的线程则获得较少的执行机会

每个线程默认的优先级都与创建它的父线程的优先级相同,默认情况下maiin线程具有普通优先级,由main线程创建的子线程也具有普通优先级

  • setPriority(int newPriority):设置优先级
  • getPriority():获得指定线程的优先级

setPriority方法的参数可以是1-10的整数,也可以是Thread类的三个常量

  • MAX_PRIORITY:值为10
  • MIN_PRIORITY :值是1
  • NORM_PRIORITY:值是5

通常建议使用三个常量来表示优先级,因为有些操作系统不支持输入数字来 表示优先级

线程同步

多线程的同步问题指的是多个线程同时修改一个数据的时候,可能导致的问题

同步代码块

在方法体内加synchronized(obj){},给对多个线程同时修改一个数据的这个变量相关代码加锁,加锁后当有一个线程在访问这个数据时,其他线程必须等当前线程执行完毕

synchronized(obj){}为同步监视器,里面的object对象是多个线程同时修改一个数据的这个变量的类对象

 public  void run()
    {
        synchronized (scanner)
        {
            //线程执行体
            Thread.currentThread().getName();
        }
       
    }

同步方法

再方法的返回值前加synchronized ,给代码加锁是需要消耗运行效率的,所以我们只对那些会改变共享变量的方法进行同步;如果可变类有两种运行环境:单线程和多线程,则需要为可变量提供两种版本,一种不加锁,一种加锁的

public  synchronized  void add()
    {
            //线程执行体
            Thread.currentThread().getName();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值