当前位置: 代码迷 >> 综合 >> SE02 Unit04 多线程基础
  详细解决方案

SE02 Unit04 多线程基础

热度:66   发布时间:2023-12-11 15:08:44.0

线程

线程用于并发执行多个任务。感官上像是”同时”执行

创建线程有两种方式。

方式一:

继承线程并重写run方法来定义线程要执行的任务代码

 package day09;
/*** 线程* 线程用于并发执行多个任务。感官上像是"同时"执行* * 创建线程有两种方式。* 方式一:* 继承线程并重写run方法来定义线程要执行的任务代码* @author adminitartor**/
public class ThreadDemo1 {
    public static void main(String[] args) {Thread t1 = new MyThread1();Thread t2 = new MyThread2();/** 启动线程要调用start方法,不要直接调用* run方法。* 当线程启动后,被分配时间片开始运行时会* 自动调用run方法。*/t1.start();t2.start();}
}
/*** 第一种创建线程存在两个不足:* 1:由于java是单继承,所以导致继承了Thread不能* 在继承其他类,在实际开发中经常会出现继承冲突* 问题* 2:由于重写线程run方法,将线程要执行的任务定义* 在了线程中,导致任务与线程有一个耦合关系,* 不利于线程重用。 * @author adminitartor**/
class MyThread1 extends Thread{
    public void run(){for(int i=0;i<1000;i++){System.out.println("你是谁啊?");}}
}
class MyThread2 extends Thread{
    public void run(){for(int i=0;i<1000;i++){System.out.println("我是查水表的!");}}
}

方式二:创建线程的方式

实现Runnable接口单独定义任务

 package day09;
/*** 方式二:创建线程的方式* 实现Runnable接口单独定义任务* @author adminitartor**/
public class ThreadDemo2 {
    public static void main(String[] args) {Runnable r1 = new MyRunnable1();Runnable r2 = new MyRunnable2();Thread t1 = new Thread(r1);Thread t2 = new Thread(r2);t1.start();t2.start();}
}
class MyRunnable1 implements Runnable{
    public void run(){for(int i=0;i<1000;i++){System.out.println("你是谁啊?");}}
}
class MyRunnable2 implements Runnable{
    public void run(){for(int i=0;i<1000;i++){System.out.println("我是查水表的!");}}
}

用匿名内部类形式完成线程两种方式的创建

package day09;
/*** 用匿名内部类形式完成线程两种方式的创建* @author adminitartor**/
public class ThreadDemo3 {
    public static void main(String[] args) {//方式一Thread t1 = new Thread(){public void run(){for(int i=0;i<1000;i++){System.out.println("你是谁啊?");}}};//方式二Runnable runn = new Runnable(){public void run(){for(int i=0;i<1000;i++){System.out.println("我是查水表的!");}}};Thread t2 = new Thread(runn);t1.start();t2.start();}
}

线程提供了一个静态方法currentThread

该方法可以获取运行该方法的线程。

 package day09;
/*** 线程提供了一个静态方法currentThread* 该方法可以获取运行该方法的线程。* java中所有代码都是线程运行的,main方法也不例外。* 当虚拟机启动后会创建一个线程来执行main方法。* @author adminitartor**/
public class Thread_CurrentThread {
    public static void main(String[] args) {//获取了运行main方法的线程Thread main = Thread.currentThread();System.out.println("运行main方法的线程是:"+main);dosome();//自定义线程Thread t = new Thread(){public void run(){Thread t = Thread.currentThread();System.out.println("自定义线程:"+t);dosome();}};t.start();}public static void dosome(){Thread t = Thread.currentThread();System.out.println("运行dosome方法的线程是:"+t);}}

线程提供了获取相关信息的方法

package day09;
/*** 线程提供了获取相关信息的方法* @author adminitartor**/
public class Thread_Info {
    public static void main(String[] args) {//获取运行main方法的线程Thread main = Thread.currentThread();long id = main.getId();System.out.println("id:"+id);String name = main.getName();System.out.println("name:"+name);int priority = main.getPriority();System.out.println("优先级:"+priority);boolean isAlive = main.isAlive();System.out.println("isAlive:"+isAlive);//是否是守护线程boolean isDaemon = main.isDaemon();System.out.println("isDaemon:"+isDaemon);//是否被中断boolean isInterrupted = main.isInterrupted();System.out.println("isInterrupted:"+isInterrupted);}
}

线程的优先级

线程的优先级有10个等级,分别用数字1-10表示
其中1最低,10最高,5为默认值

package day09;
/*** 线程的优先级* 线程的优先级有10个等级,分别用数字1-10表示* 其中1最低,10最高,5为默认值* 也可以使用线程提供的常量:* MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY* @author adminitartor**/
public class Thread_Priority {
    public static void main(String[] args) {Thread min = new Thread(){public void run(){for(int i=0;i<10000;i++){System.out.println("min");}}};Thread max = new Thread(){public void run(){for(int i=0;i<10000;i++){System.out.println("max");}}};Thread norm = new Thread(){public void run(){for(int i=0;i<10000;i++){System.out.println("nor");}}};        min.setPriority(Thread.MIN_PRIORITY);max.setPriority(Thread.MAX_PRIORITY);min.start();norm.start();max.start();}
}

Thread提供了一个静态方法

static void sleep(long ms)
该方法可以让运行该方法的线程阻塞指定毫秒,当阻塞超时后线程会回到RUNNABLE状态等待再次并发运行

package day09;import java.text.SimpleDateFormat;
import java.util.Date;/*** Thread提供了一个静态方法* static void sleep(long ms)* 该方法可以让运行该方法的线程阻塞指定毫秒,当* 阻塞超时后线程会回到RUNNABLE状态等待再次并发* 运行* @author adminitartor**/
public class Thread_Sleep {
    public static void main(String[] args) {
// 15:48:33SimpleDateFormat sdf= new SimpleDateFormat("HH:mm:ss");while(true){System.out.println(sdf.format(new Date()));try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

守护线程

守护线程也称为:后台线程

package day09;
/*** 守护线程* 守护线程也称为:后台线程* 使用上与普通线程没差别,但是结束时机上有所不同* 当一个进程结束时,该进程中的所有守护线程都要强制* 结束。* 当一个进程中的所有前台线程(普通线程)都结束使,* 进程结束。* @author adminitartor**/
public class Thread_Daemon {
    public static void main(String[] args) {Thread rose = new Thread(){public void run(){for(int i=0;i<10;i++){System.out.println("rose:let me go!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("rose:啊啊啊啊啊啊AAAAAAAaaaa....");System.out.println("音效:噗通!");}};Thread jack = new Thread(){public void run(){while(true){System.out.println("jack:you jump!i jump!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};rose.start();//设置为后台线程,必须在start之前设置jack.setDaemon(true);jack.start();}
}

线程提供了一个方法:void join()

该方法是用来协调线程间同步运行的。
异步:各干各的
同步:有先后顺序的执行

package day09;
/*** 线程提供了一个方法:void join()* 该方法是用来协调线程间同步运行的。* 异步:各干各的* 同步:有先后顺序的执行* @author adminitartor**/
public class Thread_Join {
    //表示图片是否下载完完毕的状态public static boolean isFinish = false;public static void main(String[] args) {final Thread download = new Thread(){public void run(){System.out.println("down:开始下载图片...");for(int i=1;i<=100;i++){System.out.println("down:"+i+"%");try {Thread.sleep(50);} catch (InterruptedException e) {}}System.out.println("down:图片下载完毕!");isFinish = true;}};Thread show = new Thread(){public void run(){System.out.println("show:开始显示图片...");//先等待下载完成将图片下载完毕try {/** show线程执行到join方法时会进入* 阻塞状态,直到download线程执行* 完毕,才会解除阻塞。*/download.join();} catch (InterruptedException e) {e.printStackTrace();}if(!isFinish){throw new RuntimeException("图片没有下载完毕!");}System.out.println("show:显示图片完毕!");}};download.start();show.start();}
}