线程操作的方法

线程状态 的图中可以发现,在Java实现多线程的程序中,虽然Thread类实现了Runnable接口,但是操作线程的主要方法并不在Runnable接口中,而是在Thread类中。

Thread类中主要方法
方法名称类型概述
public Thread(Runnable target)构造接收Runnable接口子类对象,实例化Thread对象
public Thread(Runnable target,String name)构造接收Runnable接口子类对象,实例化Thread对象,并设置线程名称
public void run()普通执行线程
。。。。。。。。。。
public final void setDemo(boolean on)普通将一个线程设置成后台运行

下面介绍几种常用的线程操作方法。

  1. 取得和设置线程的名称
    在Thread类中可以通过getName()方法取得线程的名称,还可以通过setName()方法设置线程的名称。
    线程的名称一般在启动线程前就设置,但是也可以为在运行的线程设置名称。允许两个线程拥有相同的名称,但应该尽量避免这种情况的发生。
    如果没有设置线程的名称,系统会为其自动分配名称。
    【取得和设置线程的名称】
class MyThread implements Runnable{
    public void run(){
            for(int i=0;i<3;i++){   
                     System.out.println(Thread.currentThread().getName()+
                        "运行,i="+i);//取得线程的名称
            }
    }
};
public class ThreadNameDemo{
    public static void main(String args[]){
        MyThread my=new MyThread();//定义Runnable子类对象
        new Thread(my).start();//系统自动设置线程的名称
        new Thread(my,"线程-A").start();//手动设置线程的名称
        new Thread(my,"线程-B").start();
        new Thread(my).start();
    }
}

运行结果:

线程-A运行,i=0
Thread-1运行,i=0
线程-B运行,i=0
线程-B运行,i=1
线程-B运行,i=2
Thread-0运行,i=0
Thread-1运行,i=1
线程-A运行,i=1
Thread-1运行,i=2
Thread-0运行,i=1
Thread-0运行,i=2
线程-A运行,i=2

从程序的运行结果中可以发现,没有设置线程名称的线程对象也有了名字而且都是有规律的,分别是Thread-1、Thread-0,从之前讲解的static关键字可以知道,在Thread类中避让存在一个static类型的属性,用于为线程的命名。
了解了以上代码后,下面观察以下的代码
【观察代码的输出】

class MyThread implements Runnable
{
    public void run(){
        for (int i=0;i<3 ;i++ )
        {
            //取得当前线程的名字
            System.out.println(Thread.currentThread().getName()+"运行, i="+i);
        }
    }
}
public class CurrentThreadDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();//定义Runnable子类对象
        new Thread(my,"线程").start();//启动线程
        my.run();//直接使用run方法
    }
}

运行结果:

main运行, i=0
线程运行, i=0
main运行, i=1
main运行, i=2
线程运行, i=1
线程运行, i=2

在以上程序中,主方法直接通过Runnable接口的子类对象调用其中的run()方法,另外一个是通过线程对象调用start()方法启动的,从结果中可以发现,主方法实际上也是一个线程。

另外要提醒的是,在java中所有的现车都是同时启动的,哪个线程先抢到了CPU的资源,哪个线程就先运行。
说明:Java程序中每次裕兴程序至少启动两个线程。 从之前的学习中可以知道,每当使用Java命令执行一个类时,实际上都会启动一个JVM,每个JVM实际上就是在操作系统中启动了一个进程,,Java本身具有垃圾回收机制。所以在Java运行时至少会启动两个线程,一个main线程,另一个就是垃圾收集线程。
2. 判断线程是否启动
通过前面的讲解可知,通过Thread类中的start()方法通知CPU这个线程已经准备好启动了,然后等待CUP资源,运行此线程,在Java中可以使用isAlive()方法来测试是否已经启动而且任然在运行。
【判断线程是否启动】

class MyThread implements Runnable{
    public void run(){//覆写run()方法
            for(int i=0;i<3;i++){   
                     System.out.println(Thread.currentThread().getName()+
                        "运行,i="+i);//取得线程的名称
            }
    }
};
public class ThreadAliveDemo
{
    public static void main(String args[])
    {
        MyThread my = new MyThread();//实例化Runnable子类对象
        Thread t=new Thread(my,"线程");//实例化Thread对象
        System.out.println("线程开始执行之前--》"+t.isAlive());//判断线程是否启动
        t.start();//启动线程
        System.out.println("线程开始执行之后——》"+t.isAlive());//判断线程是否启动
        for (int i=0;i<3 ;i++ )//循环输出三次
        {
            System.out.println("main 运行--》"+i);
        }
        System.out.println("代码执行之后--》"+t.isAlive());//后面的输出结果不确定

    }
}

运行结果:

线程开始执行之前--》false
线程开始执行之后——》true
main 运行--》0
main 运行--》1
main 运行--》2
代码执行之后--》true
线程运行,i=0
线程运行,i=1
线程运行,i=2

以上的代码运行结果是不确定的,有可能到最后线程已经不存活了,但也有可能继续存活,这要看哪个线程先运行。因为线程操作的不确定性,所以当主线程结束时,那么其他线程不会受到影响,并不会随着主线程的结束而结束。
3. 线程的强制运行
在线程操作中,可以使用join()方法让一个线程强制运行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后才能继续执行。
【线程的强制运行】

class MyThread implements Runnable
{
    public void run(){
        for (int i=0;i<20 ;i++ )
        {
            System.out.println(Thread.currentThread().getName()+"运行--》"+i);
        }
    }
};
public class ThreadJoinDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();
        Thread t=new Thread(my,"线程");
        t.start();
        for (int j=0;j<10 ;j++ )
        {
            if (j>5)
            {
                try
                {
                    t.join();//强制t进行强制进行
                }
                catch (Exception e)
                {
                }
            }
            System.out.println("Main 线程运行-->"+j);
        }
    }
}
运行结果:
Main 线程运行-->0
线程运行--》0
Main 线程运行-->1
Main 线程运行-->2
Main 线程运行-->3
线程运行--》1
Main 线程运行-->4
线程运行--》2
Main 线程运行-->5
线程运行--》3
线程运行--》4
线程运行--》5
线程运行--》6
线程运行--》7
线程运行--》8
线程运行--》9
线程运行--》10
线程运行--》11
线程运行--》12
线程运行--》13
线程运行--》14
线程运行--》15
线程运行--》16
线程运行--》17
线程运行--》18
线程运行--》19
Main 线程运行-->6
Main 线程运行-->7
Main 线程运行-->8
Main 线程运行-->9

从上面的结果可以看出,主线程必须等待这个强制运行的线程完成之后才会继续执行。
4. 线程的休眠
在程序中允许一个线程进行暂时休眠,直接调用Thread.sleep()方法即可实现休眠。
【线程的休眠】

class MyThread implements Runnable
{
    public void run(){
        for (int i=0;i<5 ;i++ )
        {
            try
            {
                Thread.sleep(500);//线程休眠
            }
            catch (Exception e)
            {   
            }
            System.out.println(Thread.currentThread().getName()+"运行,i="+i);
        }
    }
};
public class ThreadSleepDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();//实例化对象
        new Thread(my,"线程").start();//启动线程
    }
}

运行结果:

线程运行,i=0
线程运行,i=1
线程运行,i=2
线程运行,i=3
线程运行,i=4

以上程序在执行时,每次输出都会间隔500ms,达到延迟操作的效果。
5. 中断线程
当一个线程运行时,另一个线程可以通过interrupt()方法即可实现休眠。
【线程的中断】

class MyThread implements Runnable
{
    public void run(){
        System.out.println("1、进入run方法 ");
        try
        {
            Thread.sleep(10000);//休眠10s
            System.out.println("2、已经完成休眠");
        }
        catch (Exception e)
        {
            System.out.println("3、休眠被终止了");
            return;//让程序返回被调用处
        }
    }
}
public class ThreadInterruptDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();//实例化Runnable接口对象
        Thread t=new Thread(my,"线程");//实例化线程对象
        t.start();
        try
        {
            Thread.sleep(2000);//停止2S后再中断
        }
        catch (Exception e)
        {
        }
        t.interrupt();//中断线程
    }
}

运行结果:

1、进入run方法 
3、休眠被终止了

从以上程序运行的结果可以看出,一个线程启动之后进入了休眠状态,原本是休眠10s后继续运行,但是主方法在线程启动的2s后就将其中断了,休眠一旦中断,就执行catch中的代码,并利用里面的return语句返回程序的调用处。
6. 后台线程
在Java程序中,只要前台有一个线程在运行,则整个Java进程就不会消失,所以此时可以设置一个后台线程,这样Java进程结束了,此后台线程依然会继续执行。使用setDaemon()方法即可。
【后台线程的设置】

class MyThread implements Runnable
{
    public void run(){


        while (true)//无限循环
        {
            System.out.println(Thread.currentThread().getName()+"在运行。");

        }
    }
}
public class ThreadDaemonDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();
        Thread t=new Thread(my,"线程");
        t.setDaemon(true);//设置为后台线程
        t.start();
    }
}

在线程MyThread类中,尽管run()方法中是死循环的方式,但是程序依然可以执行完,因为方法在中死循环的线程操作已经设置为了后台运行了。
7. 线程的优先级
在Java的线程操作中,所有的线程在运行前都会保持在就绪状态,那么此时,哪个线程的优先级高,哪个线程就可能会先被执行。
线程的优先级:

Created with Raphaël 2.1.0 MIN_PRIORITY NORM_PRIORITY MAX_PRIORITY

优先级越高,越有可能先执行。
在Java的线程中使用setPriority()方法可以设置一个线程的优先级,在Java的线程中一共有3中优先级:

定义描述表示的常量
public static final MIN_PRIORITY最低优先级1
public static final NORM_PRIORITY中等优先级,线程的默认优先级5
public static final MAX_PRIORITY最高优先级10

不同优先级的线程执行结果。
【测试线程优先级】

class MyThread implements Runnable
{
    public void run(){
        for (int i=0;i<5 ;i++ )
        {
            try
            {
                Thread.sleep(500);
            }
            catch (Exception e)
            {
            }
            System.out.println(Thread.currentThread().getName()+"运行,i="+i);
        }
    }
};
public class ThreadPriorityDemo
{
    public static void main(String[] args)
    {
        Thread t1=new Thread(new MyThread(),"线程A");
        Thread t2=new Thread(new MyThread(),"线程B");
        Thread t3=new Thread(new MyThread(),"线程C");
        t1.setPriority(Thread.MIN_PRIORITY);//设置优先级为最低优先级
        t2.setPriority(Thread.MAX_PRIORITY);//设置优先级为最高优先级
        t3.setPriority(Thread.NORM_PRIORITY);//设置优先级为中等优先级
        t1.start();
        t2.start();
        t3.start();
    }
}

运行结果:

线程B运行,i=0
线程A运行,i=0
线程C运行,i=0
线程B运行,i=1
线程C运行,i=1
线程A运行,i=1
线程B运行,i=2
线程C运行,i=2
线程A运行,i=2
线程B运行,i=3
线程A运行,i=3
线程C运行,i=3
线程B运行,i=4
线程C运行,i=4
线程A运行,i=4

从上面的运行结果可以观察到,线程将根据其优先级的大小来决定哪个线程会先运行,但是读者一定要注意的是,并非线程的优先级越高就一定优先执行,哪个线程先执行将由CPU决定。
主线程的优先级是NORM_PRIORITY
8. 线程的礼让
在线程操作中,也可以使用yield()方法将一个线程的操作暂时让给其他线程执行。
【线程的礼让】

class MyThread implements Runnable
{
    public void run(){
        for (int i=0;i<5 ;i++ )
        {
            System.out.println(Thread.currentThread().getName()+"运行-->"+i);
            if (i==2)
            {
                System.out.print("线程礼让:");
                Thread.currentThread().yield();//线程礼让
            }
        }
    }
};
public class ThreadYieldDemo
{
    public static void main(String args[])
    {
        MyThread my=new MyThread();
        Thread t1=new Thread(my,"线程A");
        Thread t2=new Thread(my,"线程B");
        t1.start();
        t2.start();
    }
}

运行结果:

线程A运行-->0
线程B运行-->0
线程B运行-->1
线程B运行-->2
线程礼让:线程A运行-->1
线程A运行-->2
线程礼让:线程B运行-->3
线程B运行-->4
线程A运行-->3
线程A运行-->4

从结果就可以发现,每当线程满足条件时(i==2),就会将本线程暂停,而让其他线程先执行。

好了,以上就是线程常用的几种操作了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aotulive

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值