Unit09: 多线程基础
* 线程
* 线程用于并发执行多个任务。感官上像是"同时"执行
*
* 创建线程有两种方式。
* 方式一:
* 继承线程并重写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:33 SimpleDateFormat 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(); } }