•join方法:执行该方法的线程进入阻塞状态,直到调用该方法的线程结束后再由阻塞转为就绪状态。 如下:
import java.util.Date;
import java.text.SimpleDateFormat;
public class Test {
public static void main(String[] args) {
TimeThread thread = new TimeThread();
thread.start();//还可以写成:new TimeThread().start();
CountThread countThread = new CountThread(thread);
countThread.start();
}
}//主方法
class TimeThread extends Thread {//类时间线程
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("实践2##" + new Date());
try {
sleep(10000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class CountThread extends Thread {//类计数线程
TimeThread timeThread;
CountThread(TimeThread timeThread) {//有参构造方法
this.timeThread = timeThread;//调用全局变量
}
@Override
public void run() {//重写方法
for (int i = 0; i < 50; i++) {
System.out.println("技术1¥¥¥" + i);
if (i == 2) {
try {
timeThread.join();// 执行join方法的线程堵塞,知道调用join方法的线程执行完毕//此处也可以不用创建全局变量再次调用,直接:new TimeThread().start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
解释上面join()方法:当循环执行到i为2时该行代码执行,CounterThread所创建线程进入阻塞状态,直到timeThread变量所对应线程结束, CounterThread所创建线程才能再次进入就绪状态,进而进入执行状态。
注意:1.线程对象在调用join方法前必须先调用start方法,否则该线程永远不会进入执行状态。
•interrupt方法:结束线程在调用Object类的wait方法或该类的join方法、sleep方法过程中的阻塞状态,并在调用wait、join和sleep方法处产生InterruptedException异常。
import java.util.Date;
import java.text.SimpleDateFormat;
public class Test {
public static void main(String[] args) {
TimeThread thread1 = new TimeThread();
thread1.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();//调用方法,使之堵塞
}
}
class TimeThread extends Thread {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:sss");
String beforeTime = sdf.format(new Date());
System.out.println("beforeTime: " + beforeTime);
try {
sleep(300000);
} catch (InterruptedException e) {
System.out.println("程序捕获异常!");
}
String afterTime = sdf.format(new Date());
System.out.println("afterTime: " + afterTime);
}
}
解释上面:理论上beforeTime和afterTime应该相差30秒,但因为该线程类的对象在1秒后执行了interrupt方法而使得该线程对象提前结束了阻塞状态,从而导致了beforeTime和afterTime相差少于30秒
*currentThread方法:返回当前正在执行的线程对象。
import java.util.Date;
import java.text.SimpleDateFormat;
public class Test {
public static void main(String[] args) {
TimeThread thread1 = new TimeThread();
thread1.start();
CountThread countThread = new CountThread(thread1);
System.err.println(countThread);
countThread.start();
}
}
class TimeThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("实践2##" + new Date());
try {
sleep(100000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class CountThread extends Thread {
TimeThread timeThread;
CountThread(TimeThread timeThread) {
this.timeThread = timeThread;
}
@Override
public void run() {
Thread thread=Thread.currentThread();
System.out.println(thread);
for (int i = 0; i < 50; i++) {
System.out.println("技术1¥¥¥" + i);
// if (i == 2) {
// try {
// timeThread.join();// 执行join方法的线程堵塞,知道调用join方法的线程执行完毕
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
}
}
}
如果是输出对象的getName()方法结果是一样的。下面是四个程序:
import java.util.Date;
import java.text.SimpleDateFormat;
public class Test {
public static void main(String[] args) {
Thread thread = new Thread();//这俩行也可以:Thread thread=thread.currentThread();
Thread thread2 = thread.currentThread();// 此处等效于:
/**public class Test {
public static void main(String[] args) {
Thread thread = new TimeThread();
System.out.println(thread);
thread.start();
}
}
class TimeThread extends Thread{
@Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println(thread);
}
}*/
System.out.println(thread2);
TimeThread thread1 = new TimeThread();
System.out.println(thread1);// 此处用了方法
thread1.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.interrupt();
}
}
class TimeThread extends Thread {
@Override
public void run() {
TimeThread thread = (TimeThread) TimeThread.currentThread();
//等效:Thread thread=timeThread.currentThread();
System.out.println(thread);// 此处用了方法
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:sss");
String beforeTime = sdf.format(new Date());
System.out.println("beforeTime: " + beforeTime);
try {
sleep(300000);
} catch (InterruptedException e) {
System.out.println("程序捕获异常!");
}
String afterTime = sdf.format(new Date());
System.out.println("afterTime: " + afterTime);
}
}
class CountThread extends Thread {
TimeThread timeThread;
CountThread(TimeThread timeThread) {
this.timeThread = timeThread;
}
@Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println(thread);
for (int i = 0; i < 50; i++) {
System.out.println("技术1¥¥¥" + i);
}
}
}
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test {
public static void main(String[] args) {
new TimeThread().start();
}
}
class TimeThread extends Thread{
public TimeThread(){
super("时间线程");
}
@Override
public void run() {
printTime();
}
public void printTime(){
Thread thread = Thread.currentThread();
String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
System.out.println(thread.getName()+",当前时间:"+time);
System.out.println(thread.getName()+",当前时间:"+time);
}
}
结果:
时间线程,当前时间:15:12:51
时间线程,当前时间:15:12:51
public class Test {
public static void main(String[] args) {
TimeThread timeThread = new TimeThread();
System.out.println("########"+timeThread);
timeThread.start();
timeThread.run();
}
}
class TimeThread extends Thread{
@Override
public void run() {
Thread thread = Thread.currentThread();
System.out.println("@@@@@@@@"+thread);
}
}
结果:
########Thread[Thread-0,5,main]
@@@@@@@@Thread[main,5,main]
@@@@@@@@Thread[Thread-0,5,main]
调用方法isAlive()::判定该线程是否处于就绪、运行或阻塞状态,如果是则返回true,否则返回false。
注意:•线程A执行“已死”线程B所调用的jion方法,则线程A不会阻塞。
import wo.T;
public class Test {
public static void main(String[] args) {
//isAlive是否存活
Thread thread=Thread.currentThread();
TimeThread timeThread = new TimeThread(thread);
System.out.println("########"+thread.isAlive());
timeThread.start();
}
}
class TimeThread extends Thread{
Thread thread;
public TimeThread(Thread thread) {
this.thread=thread;
}
@Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("$$$$$$$"+thread.isAlive());
}
}
结果://因为时间线程堵死了
########true
$$$$$$$false
为例子一
public class Test {
public static void main(String[] args) {
Thread thread = Thread.currentThread();
new PrintThread(thread).start();
System.out.println("main线程状态:"+thread.isAlive());
}
}
class PrintThread extends Thread{
private Thread thread;
public PrintThread(Thread thread){
this.thread = thread;
}
@Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println("main线程状态:"+thread.isAlive());
}
}
为例子二:
public class Test{
String currentTime;
public static void main(String[] args) {
Test watch = new Test();
TimeThread timeThread = watch.new TimeThread ();
timeThread.start();
watch.new DisplayThread(timeThread).start();
}
class DisplayThread extends Thread{
TimeThread timeThread;
public DisplayThread(TimeThread timeThread) {
this.timeThread = timeThread;
}
@Override
public void run() {
System.out.println("时间线程状态:"+timeThread.isAlive());
try {
sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("时间线程状态:"+timeThread.isAlive());//显示器线程阻塞500毫秒,则时间线程“必死”
try {
timeThread.join();//显示器线程执行“已死”时间线程调用的jion方法,显示器线程不会阻塞
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(currentTime);
}
}
class TimeThread extends Thread{
@Override
public void run() {
currentTime = new java.util.Date().toString();
}
}
}
结果:
时间线程状态:true
时间线程状态:false
Thu Aug 29 15:52:42 CST 2019
为例子三
下面这个不太懂为什么这个结果: 仅多加了一条时间线程的run():
import wo.T;
public class Test {
public static void main(String[] args) {
//isAlive是否存活
Thread thread=Thread.currentThread();
TimeThread timeThread = new TimeThread(thread);
System.out.println("########"+thread.isAlive());
timeThread.start();
timeThread.run();
}
}
class TimeThread extends Thread{
Thread thread;
public TimeThread(Thread thread) {
this.thread=thread;
}
@Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("$$$$$$$"+thread.isAlive());
}
}
结果:
########true
$$$$$$$true
$$$$$$$true
调用守护方法setDaemon():
•setDaemon方法:用于将一个尚未调用线程start方法的线程设置为守护线程。守护线程主要用于为其他线程的运行提供服务(Java中的垃圾回收机制就是守护线程),这种线程属于创建它的线程。
•注意:守护线程随着最后一个非守护线程的终止而终止,如下代码:
public class Test {
public static void main(String[] args) {
TimeThread timeThread = new TimeThread();
timeThread.setDaemon(true);
timeThread.start();/**线程对象调用start之前调用setDaemon且值设为true,该线程为守护线程,即随着进程中最后一个非守护线程的结束而结束。*/
try {
timeThread.sleep(12);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class TimeThread extends Thread{
@Override
public void run() {
while(true) {
System.out.println(111);
}
}
}
结果是在这12秒内非守护线程在沉睡,自然守护线程时间线程继续进行,知道一起终结。
注意:进程中所启动的其他非守护线程不会随着某一个非守护线程的结束而结束。
其他方法:
•void start():使该线程开始启动,Java 虚拟机负责调用该线程的 run() 方法。多次启动一个线程是非法的。
•void sleep(long millis):Thread类静态方法,线程进入阻塞状态,在指定时间(单位为毫秒)到达之后进入就绪状态(Runnable),而非立即进入执行状态。
•void yield():静态方法,当前线程放弃占用CPU资源,回到就绪状态,使其他优先级不低于此线程的线程有机会被执行。
•void setPriority(int newPriority):设置当前线程的优先级,线程优先级越高,线程获得执行的次数越多,Java线程的优先级用整数表示,取值范围是1~10,Thread类有以下三个静态常量:
1.static int MAX_PRIORITY 最高优先级值为10;
2.static int NORM_PRIORITY 默认优先级值为5;
3.static int MIN_PRIORITY 最低优先级值为1;
注意:同一个线程类创建的多个线程,线程优先级越高的线程获得的执行次数极有可能越多;但是不同线程类创建的线程,线程优先级越高,执行次数不一定越多,这个run方法的代码复杂度有关。
•int getPriority():获得当前线程的优先级。
import java.util.Date;
public class Test {
public static void main(String[] args) {
CounterThread countThread = new CounterThread("线程一");
countThread.start();
TimeThread timeThread = new TimeThread("线程二%%%%%%%%%%%%%%%%%");
timeThread.setPriority(6);
timeThread.start();
}
}
class TimeThread extends Thread{
@Override
public void run() {
while(true) {
System.out.println(getName()+new Date());
}//此时虽然时间线程优先级高,但代码较复杂,不一定获得执行次数就多
}
TimeThread(String name){
super(name);
}
}
class CounterThread extends Thread{
@Override
public void run() {
while(true) {
System.out.println(getName()+1111);
}
}
CounterThread(String name){
super(name);
}
}//所以用此方法时还是要想看是不是同一个类创建的,如果不是,设定优先级也没有太大的作用。