JAVA多线程

多线程概念

进程:程序使用CUP资源运行的过程。
线程:在一个进程中可以有多个线程,形成多条执行线索。
线程之间可以共享某些内存,完成其任务。

多线程:在一个应用中同时存在多个执行体,他们各自执行不同的任务。
主线程:即mian方法下的线程,但是一个程序的结束是最后一个子线程的结束而结束,并不一定的main线程结束时。

多线程优势
提高计算机系统的CPU利用率;
提高程序的响应速度;
改善程序机构。

线程的状态和生命周期

一个线程的生命周期科分为一下几个状态:

1. 新建状态(New)
调用线程的构造方法创建一个线程:

Thread thread1 = new Thread();

处于新建状态的线程没有分配到有关系统资源。

2. 可运行状态(Runnable)
处于新建状态的线程调用start()方法,使得该线程进入可运行状态。
但该线程不一定开始运行,还需要受到JVM的调度。

3. 运行状态(Running)
占用CPU资源,在实际运行中。
该状态下可能发生:
1). 线程正常结束,进入死亡状态;
2). 当前程序执行yield()方法,或当前线程由于调度策略,资源被占用,进入可运行状态;
3). 使用sleep()方法,join()方法,wait()方法,使用synchronized来获取对象锁,都可进入阻塞状态。
4. 阻塞状态
1). sleep(), wait()方法进入其他阻塞状态;
2). wait()方法进入等待阻塞状态,需要notify() or notifyall() 方法来唤醒,进入可运行状态;
3). 使用synchronized请求对象但未获得对象锁时,进入对象锁阻塞状态。

5. 死亡状态
自然死亡,强制退出程序死亡,异常未捕获死亡。

线程优先级和调度

多个线程都要执行时,优先级高的线程先执行。
线程优先级为1~10,默认为5。
线程的优先级通过setPriority()方法来进行设置。

public final void setPriority(int newPriority);
//Java定义的:
MAX_PRIORITY //10
NORM_PRIORITY// 5
MIN_PRIORITY // 1

实现多线程的方法

线程的创建需要调用Thread类的构造方法来实现:

public Thread();
public Thread(String name);
public Thread(Runnable target);
public Thread(runnable target, String name);
//参数说明
name:线程名
target: 实现了Runnable接口的对象,并重写其的run()方法。

//Runnable接口定义
public interface Runnable{
     public void run();
}

有两种方法实现线程体

  1. 继承Thread类;
//继承Thread类,并重写run()方法。
public class Hello extends Tnread{
    int i;
    public void run(){
        while(true){
            System.out.println("Hello, Peter!");
            if(i==123)
                break;
            i++;
        }
    }
}
//测试类,直接用继承Thread类的Hello类创建对象并用t1指向他,t1在调用start(),方法启动该线程。
public class testHello{
    public static void main(String[] args){
        Hello t1 = new Hello();
        t1.start();
    }
}
  1. 实现Runnable接口。
//实现Runnable接口,并重写run()方法。
public class Hello implements Runnable{
    int i;
    public void run(){
        while(true){
            System.out.println("Hi, Bob!");
            i++;
            if(i==321)
                break;
        }
    }
}
//测试类,创建Thread对象,并使用实现Runnable接口的类的对象作为Thread类的参数创建对象,
public class testHello{
    public static void main(String[] args){
        Thread t1 = new Thread(new Hello());
        t1.start();
    }
}

两种方法比较

1. 继承Thread类
优点:实现简单,在run()方法中若调用当前线程的其他方法,只需要this即可,无需使用Thread.currentThread()。
缺点:由于已经继承了Thread类,所以不能继承其他类。

2. 实现Runnable接口:
优点: 可以继承其他类,可以使用多个线程共享一个target对象。
**缺点:**实现相对复杂。

线程的常用方法

1. sleep()

try{
     .....
     Thread.sleep(long millis);//休眠单位为毫秒
}catch(InterruptedException e){
    e.printStackTrace();
}

2. isAlive()
判断指定线程是否在执行中。

3. currentThread()
Thread.currentTHread(); // 获取当前的线程。
Thread.currentThread(); //获取当前线程名称。

4. yield()
暂停当前线程,让步给其他更高优先级或相同优先级的线程。
当其他线程执行完之后,在执行该线程。

5. interrupt()
interrupt()用来唤醒处于休眠的线程。当程序调用sleep()进入休眠后,interrupt()方法是其抛出异常,重新进入排队状态。

线程的同步

线程同步:
程序中多个线程需要调用同一个方法,这个方法被synchronized修饰,因此多个线程调用该方法必须遵循synchronized规则。

例子:会计收钱,出纳花钱,二者不可同时执行账本,否则发生错乱。

public class ThreadSynchronized{
    public static void main(String[] args){
         Bank bank = new bank();
         bank.setMoney(200);
         System.out.println("目前账上有" + bank.money + "亿");
         Thread cashier, accountant;
         cashier = new Thread(bank);
         accountant = new Thread(bank);
         cashier.setName("出纳");
         accountant.setName("会计");
         cashier.start();
         accountant.start();
    }
}

Class Bank implements Runnable{
    int money;
    public void setMoney(int m);
        money = m;
    public void run(){
        if(Thread.currentThread().getName().equals("出纳"))
            SaveorTack(150);
        if(Thread.currentThread().getName().equals("会计"))
            SaveorTack(300);
    }

    public SaveorTack(int amount){
         if(Thread.currentThread().getName().equals("会计")){
         for(int i=0; i<3; i++){
              money += amount/3;
              System.out.println(Thread,currentThread().getName() + "存入" + amount/3 + "账上有" + money + "休息一会儿!");
              try{
                  Thread.sleep(100);//这时出纳不可以操作
              }catch(InteruptedException e){
                  e.printStackTrace();
              }
           }
         }
         else if(Thread.currentThread().getName().equals("会计")){
         for(int j=0; j<3; j++){
             money -= amount/3;
             System.out. println(Thread.currentThread().getName() + "支出" + amount + "账上有" + money + "休息一会儿!");
             try{
                 Thread.sleep(100);//这时会计不可以操作
             }catch(InterruptedException e){}
         }
         }
    }
}

此外,还有 wait(), notify(), notifyall() 方法用来调整线程的同步问题。
如:有时线程A的某变量需要经过线程B处理子之后才符合要求,这时。就需要先让线程A在相关位置执行wait(),等线程B执行完之后再用notifyall()通知线程A即可。

线程的联合

有时线程需要接力来完成某项任务,这时候就需要线程间联合起来。

若线程A联合线程B,那么线程A立即中断,等到线程B执行完成之后,A再继续执行。

例:
线程1:顾客买蛋糕;线程2:蛋糕师制作蛋糕;
顾客到店之后需要到等待蛋糕师做完之后,才可以取走蛋糕。

public class ThreadJoinDD{
    public static void main(String[] args){
        ThreadJoin a = new ThreadJoin();
        Thread customer = new Thread(a);
        Thread cakemaker = new Thread(a);
        customer.setName("顾客");
        cakemaker.setName("蛋糕师");
        a.setJoinThread(cakemaker);
        customer.start();
    }
}
//使用Runnable接口
public class ThreadJoin implements Runnable{
    Cake cake;
    Thread joinThread;
    public void setJoinThread(Thread e){
        joinThread = e;
    }
    public void run(){
        if(Thread.currentThread().getName().equals("顾客")){
            System.out.println(Thread.currentThread().getName() + "等待" + joinThread.getName() + "制作蛋糕!");
            try{
                joinThread.start();
                joinThread.join();
            }catch(InterruptedException e){}
            System.out.println(Thread.currentThread().getName() + "买了" + cake.name + ", 价格" + cake.price);
        }
        else if(Thread.currentThread()==joinThread){
             System.out.println(joinThread.getName() + "开始制作蛋糕,请等待。。。。");
             try{
                 Thread.sleep(2000);
             }catch(InterruptedException e){}
             cake = new  Cake("生日蛋糕", 288);
             System.out.println(joinThread.getName() + "已经完成蛋糕店制作。");
        }
    }
//内部类,Cake
    class Cake{
        int price;
        String name;
        public Cake(int price, String name){
        this.price = price;
        this.name = name;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值