线程的创建
如何创建一个线程呢?
方法如下:
1.创建一个类,使这个类继承Thread
class MyThread extends Thread{
public void run(){
while (true){ //这里加 while 是为了让线程一直执行
try {
Thread.sleep(3000); //休眠3s左右再执行 (后面会说到)
System.out.println("hello t");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadTest {
public static void main(String[] args) {
MyThread myThread = new MyThread(); //创建一个MyThread类
myThread.start(); //启动线程
while (true){
try {
Thread.sleep(1000);
System.out.println("main");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.实现Runnable 接口
class MyRunnable implements Runnable{
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("hello t");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadTest2 {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start(); //线程开始
System.out.println("hello main");
}
}
3.使用lambda表达式()->{} 常用
public class ThreadTest5 {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
while (true){
try {
Thread.sleep(1000);
System.out.println("hello t ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
while (true){
try {
Thread.sleep(2000);
System.out.println("hello main");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
4, 使用匿名内部类对上述的变形
继承 Thread, 重写 run, 使用匿名内部类
public class ThreadTest3 {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(){
public void run() {
while (true) {
try {
Thread.sleep(1000);
System.out.println("hello t");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.start();
while (true){
Thread.sleep(2000);
System.out.println("hello main");
}
}
}
实现 Runnable, 重写 run, 使用匿名内部类
public class ThreadTest4 {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
System.out.println("hello t");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
while (true){
try {
Thread.sleep(1000);
System.out.println("hello main");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程中断
当一个线程进行工作的时候,它就会按找方法进行执行,不执行完是不会结束的
但当我们想中断线程的时候怎么办,则有两种办法1.第一种就是使用自定义的变量来做标志位
2.第二种就是Thread类提供一个"中断"方法 interrupt()方法,用来通知线程结束
public void interrupt() : 中断对象关联的线程,如果线程正在阻塞,则以异常方式通知,
否则设置标志位
public static boolean interrupted() :判断当前线程的中断标志位是否设置,调用后清除标志位。
public boolean isInterrupted() : 判断对象关联的线程的标志位是否设置,调用后不清除标志位
对于标志位:即在线程中设置一个中断标志位,当中断标志位为true时,线程停止运行,当中断标志位为false时,线程继续执行
自定义变量作为标志位代码实现
public class ThreadTest16 {
public static boolean isQuit = false; // 通过自定义的变量来获得标志位
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
while (!isQuit){
try {
Thread.sleep(1000);
System.out.println("111");
} catch (InterruptedException e) {
e.printStackTrace();
}
} // 退出循环
System.out.println("t 线程停止");
});
t1.start();
Thread.sleep(3000); //3秒后使标志位为true,然后使t1线程退出循环 停止
isQuit = true;
}
}
使用 thread 对象的 interrupted() 方法通知线程结束
public class ThreadTest16 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
//isInterrupted() t1对象自带的标志位 默认为false 取反为true
while (!Thread.currentThread().isInterrupted()){
try {
Thread.sleep(1000);
System.out.println("111");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("停止");
break; //跳出循环 ,不跳出循环就会一直循环下去(sleep自动清空标志位)
}
}
});
t1.start();
Thread.sleep(3000);
t1.interrupt(); // 设置中断标识位为true,如果线程正在阻塞中(比如sleep),就会将阻塞状态唤醒,并通过抛出异常的方式让sleep立即结束
//此处注意sleep被唤醒时会自动将isInterrupted标志位清空(true变为false),导致继续循环
}
}
线程等待 join方法的应用
现实中有种情况,即当前面一个线程执行完之后后面这个线程才能进行下一步执行,而在多线程里面,线程调用是随机的,这就不能保证上述情况了, 然后发明java的大佬们就考虑到了这点,提供一个join方法来保证这点。
public void join() :让别的线程等待该线程执行完再执行
public void join(long millis) :设置一个等待时间(毫秒)
public void join(long millis, int nanos) : 设置一个等待时间(毫秒,微毫秒)
join方法代码实例
public class ThreadTest17 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()-> {
try {
Thread.sleep(2000);
System.out.println("hello 1");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t1.join(); //令t1线程先执行 然后执行main线程 即让别的线程等待该线程执行完再执行
System.out.println("hello main");
}
}
获取当前线程的引用
public static Thread currentThread(); // 返回当前线程对象的引用
获取当前线程引用代码实现
public class ThreadTest19 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
System.out.println("进入t1线程 Thread");
System.out.println(Thread.currentThread().getName() +":执行线程");
});
t1.start();
System.out.println(Thread.currentThread().getName()+ ":执行main线程");
Thread.sleep(2000);
System.out.println("main");
}
}