关闭

线程简介

标签: 线程的实现方式线程的生命周期线程的休眠和唤醒线程的优先级
139人阅读 评论(0) 收藏 举报
分类:

线程类实现了Runnable接口,则线程类的子类可以实现run方法,当获取子类的实例后可以直接启动线程,启动后直接运行run方法。多线程就是有多个线程,主线程中有一个子线程也是多线程。


1. 线程的运行状态

新建状态:new 线程后,即创建线程对象后,但还没有启动的时候

就绪状态:线程调用了start()方法启动线程,就处于就绪状态了,此时等待cpu的调度,获得周期线程就可以运行了

运行状态:获得周期线程,处于运行中,本状态下一步可能进入阻塞状态或死亡状态

阻塞状态:该状态下无法运行,满足条件后继续进入运行状态进入阻塞状态的情况

                       线程等待输入输出操作,操作完成前不会反悔调用者

                       线程调用了wait()方法或sleep()方法

                       线程需要满足某种条件才会继续运行

死亡状态:线程退出run方法就处于死亡状态。



2. 获取正在运行的线程名字

Thread类有私有的String类型的属性保存该线程的名字,当我们没有设置线程名称时在线程类内我们可以通过getName()获取,获取的名称是Thread-0 1 2,而在 主线程的地方通过线程类的静态方法Thread.currentThread()获取当前运行的线程对象,再通过getName()获取。Thread类型的构造方法中有可以传递名字的构造方法。(注意构造方法不能被继承,自己定义的线程类,若传递姓名则写自己的构造方法,将参数通过super(“”)传递给父类

 

3. 线程的优先级

线程的执行顺序是一种抢占方式,高优先级的比低优先级的获得的执行时间更多,不会对运行顺序有影响。

通过线程的setPriority()设置器优先级,其参数是1-10之间的整数:MIN_PRIORITY=1:最低优先级,MAX_PRIORITY=10:最高优先级,NORM_PRIORITY=5:默认优先级

 

4. 线程的休眠和唤醒

线程的休眠:指线程处于阻塞等待的状态,停止运行,可通过seleep()实现,该方法使线程在指定时间内处于阻塞状态,时间到后进入运行状态

线程的唤醒:使线程从阻塞状态进入运行状态,结束休眠状态,会执行sleep的捕获异常中的catch中的代码

Sleep()线程休眠:线程暂时休眠,带锁休眠,休眠后其他的线程仍然不能进入。到时间后自动唤醒。

Wait()也是让线程终止执行,不过wait会释放锁进入wait池,只能通过notify()进行唤醒

 


5.线程让步:使当前线程退出一次运行状态,其他线程谁抢占到谁运行,通过方法yield()方法

 

6. 线程的同步

线程是通过抢占实现的,优先抢占到的优先运行,若一个线程运行到一半就被另一个线程抢占了,而他们操作的变量相同,第一个线程运行仍然是以他运行到一半的地方开始,而另一个线程对数据的操作可能造成了数据的重复修改,造成数据的不准确。当对同一个变量进行操作时多用同步,使对这个变量的操作在同一时间只有一根线程执行。(例子:两个子线程同时操作一个变量值是2,第一个线程是对变量的数据-1在放回,第二个线程是对变量*2再放回去,当执行时,第一个线程取了数据-1,而此时第二个线程执行取数据则取回的是还没有修改的数据,后线程一将数据放回去,此时变量值是1,此时线程二执行变量值是4,此时则一个变量有了两个值。)

在java中的每个对象中都包含一把锁(也叫监视器),它自动成为对象的一部分(不需要写特殊的代码)。在给定时刻,只有一个线程可以拥有一个对象监视器,通过启动这把锁实现线程的同步,就实现了在同一时刻对某个变脸只有一个线程对其操作。通过 Synchronized(同步的)实现。

银行异步执行银行取款的数据错误实例:

public class MoneyThread  extends Thread{
private Bank bank;
public MoneyThread(Bank bank) {
this.bank = bank;
}
@Override
public void run() {
System.out.println("取出:"+bank.getMoney(800)+"元");
}
}

public class Bank {
private int money;
public Bank(int money) {
this.money = money;
}
public  int getMoney(int number){
if(number<0){
return -1;
}else if(number>money){
return -2;
}else{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
money-=number;
return number;
}
}
}

public class MoneyThread  extends Thread{
private Bank bank;
public MoneyThread(Bank bank) {
this.bank = bank;
}
@Override
public void run() {
System.out.println("取出:"+bank.getMoney(800)+"元");
}
}

实现方式:使用Synchronized(同步的)它用来修饰一个方法或者一个代码块的时候 ,在方法前面添加Synchronized变成同步方法,同步方法在同一时间只能被一个线程调用,调用完成后才会释放锁,被其他线程调用。当被锁状态时其他线程调用,则会进入等待状态,等待其他线程执行完后再对本线程上锁,执行。能够保证在同一时刻最多只有一个线程执行该段代码。加锁注意锁定的方法是操作变量的方法,锁定的对象在操作变量的对象

 

同步块:

通过Synchronized实现,相当于对线程上了一把锁,只有线程执行完后才能其他线程抢占执行,

使用

Synchronized(obj){

代码段

}

 

同步化方法

就是对整个方法进行同步,他是对某个方法进行设置同步,只有该方法执行完后才能执行其他的方法

使用

在方法中添加synchronized

Synchronized void FunctionName(){

 

}



线程的创建方式

1.  继承runnable接口:更加好用,实现该接口后还可以继续继承类,增加了扩展性

2.  继承Thread类:java是单继承的,只能继承一个类。

publicclassThreadOneimplementsRunnable {

 

@Override

public void run() {

     //线程中运行的方法

     for(int i=0;i<10;i++){

         System.out.println("这是继承Runable接口");}}}

 

 

public classThreadTwo extendsThread {

   

    @Override

    public void run() {

        super.run();

        for(int i=0;i<10;i++){

            System.out.println("这是继承Thread类,Thread类也实现了Runable接口可以重写run接口");

        }}}

 

 

public classFileUse{

    public static void main(String[] args) {

        Thread one=newThread(new ThreadOne());

        one.start();//开启线程

        ThreadTwotwo=newThreadTwo();

        two.start();

        for(int i=0;i<10;i++){

            System.out.println("这是主线程运行的结果");

        }

    }  

}

同步的实现

(1)同步方法:

 就是银行的类中的取款的方法进行加锁,就实现了在同一时刻只有一个线程执行取款的操作,就不会出现数据错误的问题了:

public classBank {

    private int money;

    public Bank(int money) {

        this.money = money;

    }

    public synchronized int getMoney(int number){

        if(number<0){

            return -1;

        }else if(number>money){

            return -2;

        }else{

            try {

                Thread.sleep(1000);

            }catch(InterruptedException e) {

                e.printStackTrace();

            }

            money-=number;

            return number;

        }

    }

}

(2)对代码块加同步锁

则代码块中的规定的对象在同一时刻只有一个方法执行,则该代码块在同一时刻只有一个线程执行,其中锁定的对象可以是任意对象,当该对象被锁定时,另一个线程过来看到对象已经被锁定了则回进行等待,等待对象解除锁定后在执行锁代码块中的代码。

public classBank {

    private int money;

    Objectobjecty=new Object();

    public Bank(int money) {

        this.money = money;

    }

    public int getMoney(int number){

        //这就是一个代码块,其中的对象可以是当前类的对象即this,也可以像现在一样的任意定义的一个对象。

        synchronized (objecty) {

            if(number<0){

                return -1;

            }else if(number>money){

                return -2;

            }else{

                try {

                    Thread.sleep(1000);

                }catch(InterruptedException e) {

                    e.printStackTrace();

                }

                money-=number;

                return number;

            }  

        }

    }

}




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:19446次
    • 积分:1182
    • 等级:
    • 排名:千里之外
    • 原创:96篇
    • 转载:26篇
    • 译文:3篇
    • 评论:1条
    最新评论