java 线程实现、线程暂停和终止 、线程联合join、线程基本信息获取和设置、线程优先级
转载地址:速学堂 https://www.sxt.cn/Java_jQuery_in_action/eleven-inheritthread.html
1. 通过继承Thread类实现多线程
继承Thread类实现多线程的步骤:
1. 在Java中负责实现线程功能的类是java.lang.Thread 类。
2. 可以通过创建 Thread的实例来创建新的线程。
3. 每个线程都是通过某个特定的Thread对象所对应的方法run( )来完成其操作的,方法run( )称为线程体。
4. 通过调用Thread类的start()方法来启动一个线程。
通过继承Thread类实现多线程
public class TestThread extends Thread {//自定义类继承Thread类
    //run()方法里是线程体
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(this.getName() + ":" + i);//getName()方法是返回线程名称
        }
    }
    public static void main(String[] args) {
        TestThread thread1 = new TestThread();//创建线程对象
        thread1.start();//启动线程
        TestThread thread2 = new TestThread();
        thread2.start();
    }
}
此种方式的缺点:如果我们的类已经继承了一个类(如小程序必须继承自 Applet 类),则无法再继承 Thread 类。
2 通过Runnable接口实现多线程
在开发中,我们应用更多的是通过Runnable接口实现多线程。这种方式克服了上面实现线程类的缺点,即在实现Runnable接口的同时还可以继承某个类。所以实现Runnable接口的方式要通用一些。
public class TestThread2 implements Runnable {//自定义类实现Runnable接口;
    //run()方法里是线程体;
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
    public static void main(String[] args) {
        //创建线程对象,把实现了Runnable接口的对象作为参数传入;
        Thread thread1 = new Thread(new TestThread2());
        thread1.start();//启动线程;
        Thread thread2 = new Thread(new TestThread2());
        thread2.start();
    }
}
线程状态

一个线程对象在它的生命周期内,需要经历5个状态。
▪ 新生状态(New)
用new关键字建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态。
▪ 就绪状态(Runnable)
处于就绪状态的线程已经具备了运行条件,但是还没有被分配到CPU,处于“线程就绪队列”,等待系统为其分配CPU。就绪状态并不是执行状态,当系统选定一个等待执行的Thread对象后,它就会进入执行状态。一旦获得CPU,线程就进入运行状态并自动调用自己的run方法。有4中原因会导致线程进入就绪状态:
1. 新建线程:调用start()方法,进入就绪状态;
2. 阻塞线程:阻塞解除,进入就绪状态;
3. 运行线程:调用yield()方法,直接进入就绪状态;
4. 运行线程:JVM将CPU资源从本线程切换到其他线程。
▪ 运行状态(Running)
在运行状态的线程执行自己run方法中的代码,直到调用其他方法而终止或等待某资源而阻塞或完成任务而死亡。如果在给定的时间片内没有执行结束,就会被系统给换下来回到就绪状态。也可能由于某些“导致阻塞的事件”而进入阻塞状态。
▪ 阻塞状态(Blocked)
阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪)。有4种原因会导致阻塞:
1. 执行sleep(int millsecond)方法,使当前线程休眠,进入阻塞状态。当指定的时间到了后,线程进入就绪状态。
2. 执行wait()方法,使当前线程进入阻塞状态。当使用nofity()方法唤醒这个线程后,它进入就绪状态。
3. 线程运行时,某个操作进入阻塞状态,比如执行IO流操作(read()/write()方法本身就是阻塞的方法)。只有当引起该操作阻塞的原因消失后,线程进入就绪状态。
4. join()线程联合: 当某个线程等待另一个线程执行结束后,才能继续执行时,使用join()方法。
▪ 死亡状态(Terminated)
死亡状态是线程生命周期中的最后一个阶段。线程死亡的原因有两个。一个是正常运行的线程完成了它run()方法内的全部工作; 另一个是线程被强制终止,如通过执行stop()或destroy()方法来终止一个线程(注:stop()/destroy()方法已经被JDK废弃,不推荐使用)。
当一个线程进入死亡状态以后,就不能再回到其它状态了。
终止线程的典型方式
终止线程我们一般不使用JDK提供的stop()/destroy()方法(它们本身也被JDK废弃了)。通常的做法是提供一个boolean型的终止变量,当这个变量置为false,则终止线程的运行
public class TestThreadCiycle implements Runnable {
    String name;
    boolean live = true;// 标记变量,表示线程是否可中止;
    public TestThreadCiycle(String name) {
        super();
        this.name = name;
    }
    public void run() {
        int i = 0;
        //当live的值是true时,继续线程体;false则结束循环,继而终止线程体;
        while (live) {
            System.out.println(name + (i++));
        }
    }
    public void terminate() {
        live = false;
    }
    public static void main(String[] args) {
        TestThreadCiycle ttc = new TestThreadCiycle("线程A:");
        Thread t1 = new Thread(ttc);// 新生状态
        t1.start();// 就绪状态
        for (int i = 0; i < 100; i++) {
            System.out.println("主线程" + i);
        }
        ttc.terminate();
        System.out.println("ttc stop!");
    }
}
暂停线程执行sleep/yield
暂停线程执行常用的方法有sleep()和yield()方法,这两个方法的区别是:
1. sleep()方法:可以让正在运行的线程进入阻塞状态,直到休眠时间满了,进入就绪状态。
2. yield()方法:可以让正在运行的线程直接进入就绪状态,让出CPU的使用权。
暂停线程的方法-sleep()
public class TestThreadState {
    public static void main(String[] args) {
        StateThread thread1 = new StateThread();
        thread1.start();
        StateThread thread2 = new StateThread();
        thread2.start();
    }
}
//使用继承方式实现多线程
class StateThread extends Thread {
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(this.getName() + ":" + i);
            try {
                Thread.sleep(2000);//调用线程的sleep()方法;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
执行结果如图所示(注:以下图示只是部分结果,运行时可以感受到每条结果输出之前的延迟,是Thread.sleep(2000)语句在起作用):

暂停线程的方法-yield()
public class TestThreadState {
    public static void main(String[] args) {
        StateThread thread1 = new StateThread();
        thread1.start();
        StateThread thread2 = new StateThread();
        thread2.start();
    }
}
//使用继承方式实现多线程
class StateThread extends Thread {
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(this.getName() + ":" + i);
            Thread.yield();//调用线程的yield()方法;
        }
    }
}
执行结果如图所示(注:以下图示只是部分结果,可以引起线程切换,但运行时没有明显延迟):

线程的联合join()
线程A在运行期间,可以调用线程B的join()方法,让线程B和线程A联合。这样,线程A就必须等待线程B执行完毕后,才能继续执行。如下面示例中,“爸爸线程”要抽烟,于是联合了“儿子线程”去买烟,必须等待“儿子线程”买烟完毕,“爸爸线程”才能继续抽烟。
public class TestThreadState {
    public static void main(String[] args) {
        System.out.println("爸爸和儿子买烟故事");
        Thread father = new Thread(new FatherThread());
        father.start();
    }
}
class FatherThread implements Runnable {
    public void run() {
        System.out.println("爸爸想抽烟,发现烟抽完了");
        System.out.println("爸爸让儿子去买包红塔山");
        Thread son = new Thread(new SonThread());
        son.start();
        System.out.println("爸爸等儿子买烟回来");
        try {
            son.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("爸爸出门去找儿子跑哪去了");
            // 结束JVM。如果是0则表示正常结束;如果是非0则表示非正常结束
            System.exit(1);
        }
        System.out.println("爸爸高兴的接过烟开始抽,并把零钱给了儿子");
    }
}
class SonThread implements Runnable {
    public void run() {
        System.out.println("儿子出门去买烟");
        System.out.println("儿子买烟需要10分钟");
        try {
            for (int i = 1; i <= 10; i++) {
                System.out.println("第" + i + "分钟");
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("儿子买烟回来了");
    }
}
执行结果如图:

获取线程基本信息的方法

线程的常用方法一
public class TestThread {
    public static void main(String[] argc) throws Exception {
        Runnable r = new MyThread();
        Thread t = new Thread(r, "Name test");//定义线程对象,并传入参数;
        t.start();//启动线程;
        System.out.println("name is: " + t.getName());//输出线程名称;
        Thread.currentThread().sleep(5000);//线程暂停5分钟;
        System.out.println(t.isAlive());//判断线程还在运行吗?
        System.out.println("over!");
    }
}
class MyThread implements Runnable {
    //线程体;
    public void run() {
        for (int i = 0; i < 10; i++)
            System.out.println(i);
    }
}
执行结果:

线程的优先级
1. 处于就绪状态的线程,会进入“就绪队列”等待JVM来挑选。
2. 线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级是5。
3. 使用下列方法获得或设置线程对象的优先级。
int getPriority();
void setPriority(int newPriority);
注意:优先级低只是意味着获得调度的概率低。并不是绝对先调用优先级高的线程后调用优先级低的线程。
线程的常用方法二
public class TestThread {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyThread(), "t1");
        Thread t2 = new Thread(new MyThread(), "t2");
        t1.setPriority(1);
        t2.setPriority(10);
        t1.start();
        t2.start();
    }
}
class MyThread extends Thread {
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}
执行结果:

java 线程实现、线程暂停和终止 、线程联合join、线程基本信息获取和设置、线程优先级的更多相关文章
- java 22 - 5 多线程之获取和设置线程对象的名称
		如何获取线程对象的名称呢? public final String getName():获取线程的名称.如何设置线程对象的名称呢? public final void setName(String n ... 
- Java并发学习之二——获取和设置线程信息
		本文是学习网络上的文章时的总结,感谢大家无私的分享. Thread类的对象中保存了一些属性信息可以帮助我们辨别每个线程.知道它的一些信息 ID:每一个线程的独特标示: Name:线程的名称: Prio ... 
- java利用反射机制判断对象的属性是否为空以及获取和设置该属性的值
		1.java利用反射机制判断对象的属性是否为空: Map<String,String> validateMap = new LinkedHashMap<String, String& ... 
- java并发编程(四) 线程池 & 任务执行、终止源码分析
		参考文档 线程池任务执行全过程:https://blog.csdn.net/wojiaolinaaa/article/details/51345789 线程池中断:https://www.cnblog ... 
- Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)
		Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ... 
- java 之Thread线程相关yield()、sleep()、wait()、join()、run和start方法详解
		1.sleep() 使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁.也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据.注意该方 ... 
- 【转】Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)
		一.线程的状态 Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态). New:新建状态,当线 ... 
- java 22 - 6 多线程之线程调度和设置线程的优先级
		线程调度 假如我们的计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到 CPU时间片,也就是使用权,才可以执行指令. 那么Java是如何对线程进行调用的呢? 线程有两种调 ... 
- JAVA之旅(十二)——Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口
		JAVA之旅(十二)--Thread,run和start的特点,线程运行状态,获取线程对象和名称,多线程实例演示,使用Runnable接口 开始挑战一些难度了,线程和I/O方面的操作了,继续坚持 一. ... 
随机推荐
- 一个机器绑两个IP可能存在的问题
			1.同一网段两个ip 无法绑到一个机器上. 因为会生成两条该网段路由,两个路由用于同网段报文相应,而实际ip选路时只会选择其中一条路由(估计会选择前面那一条)从一个网卡走.这样不管哪个网卡来的局域网内 ... 
- C# mvc后台传过来的list 怎么在js使用
			var arr= JSON.parse('@Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize( ... 
- shell编程系列2--字符串的处理
			shell编程系列2--字符串的处理 字符串的处理 .计算字符串的长度 方法1 ${#string} 方法2 expr length "$string" (如果string中间有空 ... 
- 002-05-RestTemplate 使用常见问题-非200请求捕获
			一.概述 1.1.RestTemplate报错时时获取不到错误信息 捕获异常后 try { result = restTemplate.postForEntity(faceConfig.getApiU ... 
- 123457123456#1#----com.MC.CarWashKidsGames234----前拼后广--洗车游戏mc-mc1111
			com.MC.CarWashKidsGames234----前拼后广--洗车游戏mc-mc1111 
- DB2中ALTER TABLE的使用
			今天在看DB2存储过程的时候发现了如下语句能够清空表: ... SET EX_SQL='ALTER TABLE TEST_TABLE ACTIVATE NOT LOGGED INITIALLY WIT ... 
- 组件文档系统-md-react-styleguidist
			推荐指数: 
- 如何固定table表格宽度,样式不受容器影响
			之前有篇关于LODOP打印超文本表格,两个样式相同的表格,出现错位的情况.该博文地址:LODOP打印表格错位的几种情况该文试验了两种现象,第一种浏览器页面显示错位,打印预览也错位,第二种浏览器页面表格 ... 
- java四大名著及idea常用插件
			四大名著 <Java编程思想><Think in Java> https://github.com/quanke/think-in-java https://github.co ... 
- Python文件的读取写入操作
			一.打开文件.关闭文件操作 想要读取文件或是写入文件,第一步便是打开文件,最后一步便是关闭文件.这里介绍两种打开(关闭)文件的方式: 1.open()方法 f=open(file_name[,acce ... 
