博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【JavaSE】day13_多线程
阅读量:4305 次
发布时间:2019-05-27

本文共 8380 字,大约阅读时间需要 27 分钟。

【JavaSE】day13_多线程

1.线程

1)线程

 * 并发运行,可以"同时"完成多个任务。

2)线程有两种创建模式

 * 模式1:

 * 定义一个类并继承Thread,然后重写run方法,在内部编写该程序要执行的任务。

3)注意!启动线程不要直接调用run方法。而是调用start方法。

    * 该方法会将当前线程注册到线程调度中,使其可以并发运行。start方法调用完毕后意味着当前线程进入了runnable状态,一旦被线程调度分配时间片就开始运行。

    * 线程对于线程调度的工作不可控:

         * CPU时间片分配给哪个线程不可控。

         * 时间片长短不可控。

    * 不过线程调度会尽可能的均匀的将时间片分配给每个线程。

代码演示:

package day04;/** * 线程 * 并发运行,可以"同时"完成多个任务。 *  * 线程有两种创建模式 * 模式1: * 定义一个类并继承Thread,然后重写run方法,在内部编写该程序 * 要执行的任务。 *  */public class ThreadDemo1 {	public static void main(String[] args) {		Thread t1 = new MyThread1();				Thread t2 = new MyThread2();				/*		 * 注意!启动线程不要直接调用run方法。而是调用start方法。		 * 该方法会将当前线程注册到线程调度中,使其可以并发运行。		 * start方法调用完毕后意味着当前线程进入了runnable状态,		 * 一旦被线程调度分配时间片就开始运行。		 * 		 * 线程对于线程调度的工作不可控:		 * CPU时间片分配给哪个线程不可控。		 * 时间片长短不可控。		 * 		 * 不过线程调度会尽可能的均匀的将时间片分配给每个线程。		 */		t1.start();		t2.start();			}}/* * 第一种创建线程的方式存在两个弊端: * 1:由于java是单继承的,所以若我们继承了Thread就无法继承 *    其他类,这对于项目开发而言是不可容忍的。 * 2:重写run方法会导致线程与线程要执行的任务有一个耦合关系, *    这导致当前线程只会完成该任务,不利于线程的重用。 * 第一种创建线程也存在一个优点: * 定义简便。当我们需要临时使用一个线程完成某个任务时通常会使用 * 匿名内部类,这时用第一种方式创建比较理想。 */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("我是查水表的");		}	}}

2.线程的第二种创建模式:

package day04;/** * 线程的第二种创建模式: * 1:单独定义线程要执行的任务 *    定义一个类,实现Runnable接口,并重写run方法 * 2:创建线程并将任务指派进去再启动。 * * 优点: * 1:单独定义任务,在用的时候才指派线程,所以与线程 *    没有必然的耦合关系,利于线程重用。 * 2:由于任务类是实现Runnable接口,java接口是多实现的, *    所以无论是继承其他类还是实现其他接口都不再受影响。 */public class ThreadDemo2 {	public static void main(String[] args) {		//创建任务		Runnable runn1 = new MyRunnable1();		Runnable runn2 = new MyRunnable2();				//创建线程,并指派任务给线程		Thread t1 = new Thread(runn1);		Thread t2 = new Thread(runn2);				//启动线程		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("我是查水表的");		}	}}

3.匿名内部类的形式创建线程

package day04;/** * 练习使用匿名内部类的形式创建线程 */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();	}}

4.Thread currentThread()

package day04;/** * Thread提供了一个静态方法currentThread, * 该方法可以获取运行这个方法的线程。 *  * 实际上main方法也是靠一个线程运行的,只是该 * 线程不是由我们直接创建的。 * */public class ThreadDemo4 {	public static void main(String[] args) {		//获取运行main方法的线程		Thread t = Thread.currentThread();		System.out.println(t);				dosome();				Thread my = new Thread(){			public void run(){				Thread t = Thread.currentThread();				System.out.println(t); //自定义线程my								dosome();			}		};		my.start();	}		public static void dosome(){		Thread t = Thread.currentThread();		System.out.println("dosome:"+t);	}}

5.获取线程状态的相关方法

package day04;/** * 获取线程状态的相关方法 * */public class ThreadDemo5 {	public static void main(String[] args) {		Thread t = Thread.currentThread();		//获取线程id		System.out.println("id:"+t.getId());		//获取线程名字		System.out.println("name:"+t.getName());		//获取线程优先级		System.out.println("priority:"+t.getPriority());		//获取是否活着		System.out.println("isAlive:"+t.isAlive());		//是否为后台线程		System.out.println("isDaemon:"+t.isDaemon());		//是否被中断了		System.out.println("isInterrupted:"+t.isInterrupted());	}}

6.线程优先级

package day04;/** * 线程优先级 * 优先级有10个等级,1-10,其中1最低,10最高,默认为5 * 有三个常量可以对应最低,最高,默认优先级 * Thread.MIN_PRIORITY  ==> 1 * Thread.MAX_PRIORITY  ==> 10 * Thread.NORM_PRIORITY ==> 5 * */public class ThreadDemo6 {	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("norm");				}			}		};				min.setPriority(Thread.MIN_PRIORITY);		max.setPriority(10);				min.start();		norm.start();		max.start();					}}

7.sleep()方法

package day05;import java.text.SimpleDateFormat;import java.util.Date;/** * Thread提供了一个静态方法sleep,该方法可以使运行该方法的线程阻塞 * 指定毫秒。当阻塞时间超时后,该线程会自动回到runnable状态,等待再 * 次分配时间片然后运行。 * */public class ThreadDemo1 {	public static void main(String[] args) {		/*		 * 电子表,每秒钟输出当前系统时间:HH:mm:ss		 */		Date date = null;		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");		while(true){						date = new Date();			String str = sdf.format(date);			System.out.println(str);			try {				/*				 * sleep做不到严格意义上的间隔				 * 可以保证1秒的阻塞,但是解除阻塞后线程回到runnable状态,				 * runnable到run这个等待时间就是误差。				 */				Thread.sleep(1000);			} catch (InterruptedException e) {				e.printStackTrace();			}		}							}}

8.守护线程,又称后台线程

package day05;/** * 守护线程,又称后台线程 * 当一个进程中的所有前台线程都结束时,进程就要结束, * 无论后台线程是否还处于运行状态,都要强制中断。 */public class ThreadDemo2 {	public static void main(String[] args) {		//rose:前台线程		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("......");			}		};		//jack:后台线程		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();			}}

9.join()方法

package day05;/** * join方法 * join方法会阻塞运行该方法的线程,允许该线程在另一个 * 线程上等待,直到那个线程的工作结束,当前线程才会解除 * 阻塞继续运行。 * 该方法通常为了实现两个线程间同步(有先后顺序工作)的情况。 * */public class ThreadDemo3 {	//标示图片是否下载完毕	public static boolean isFinish;		public static void main(String[] args){		/*		 * 下载线程		 */		final Thread download = new Thread(){			public void run(){				System.out.println("download:开始下载...");				for(int i=0;i<=100;i+=10){					System.out.println("download:"+i+"%");					try {						Thread.sleep(500);					} catch (InterruptedException e) {						e.printStackTrace();					}				}				System.out.println("download:下载完毕!");				isFinish = true;			}		};				/*		 * 显示线程		 */		Thread show = new Thread(){			public void run(){				System.out.println("show:开始显示图片!");				/*				 * 显示之前应该等待下载完毕!				 */				try{					/*					 * 一个方法中的局部内部类中若想引用这个方法的其他					 * 局部变量,那么这个变量必须是final的。					 */					download.join();				}catch(InterruptedException e){					e.printStackTrace();				}				if(!isFinish){					/*					 * 当线程抛出一个未捕获的异常时,该线程直接被kill					 */					throw new RuntimeException("图片显示失败");				}				System.out.println("图片显示完毕!");			}		};				download.start();		show.start();			}}

10.wait()、notify()

package day05;/** * object中定义了两个方法wait,notify * 当一个线程调用了一个对象的wait方法后,该线程进入阻塞状态, * 直到这个对象的notify方法被调用才可以解除阻塞.对于协调 * 线程同步而言,这种方式比join的即时性强,因为join必须被动 * 的等待其他线程完成所有工作. * */public class ThreadDemo4 {	//标示图片是否下载完毕	public static boolean isFinish;		public static Object obj = new Object();		public static void main(String[] args) {		/*		 * 下载线程		 */		final Thread download = new Thread(){			public void run(){				System.out.println("download:开始下载图片...");				for(int i=0;i<=100;i+=10){					System.out.println("download:"+i+"%");					try {						Thread.sleep(500);					} catch (InterruptedException e) {						e.printStackTrace();					}				}				System.out.println("download:图片下载完成");				isFinish = true;								//当图片下载完毕,就可以通知显示线程显示图片了。				synchronized(obj){					obj.notify();				}								//下载附件				System.out.println("开始下载附件...");				for(int i=0;i<=100;i+=20){					System.out.println("download:"+i+"%");					try {						Thread.sleep(500);					} catch (InterruptedException e) {						e.printStackTrace();					}				}				System.out.println("download:附件下载完毕");							}		};				/*		 * 显示线程		 */		final Thread show = new Thread(){			public void run(){				System.out.println("开始显示图片...");								try {					synchronized(obj){						obj.wait();					}				} catch (InterruptedException e) {					e.printStackTrace();				}								if(!isFinish){					throw new RuntimeException("show error");				}								System.out.println("图片显示完毕");			}		};						download.start();		show.start();			}}

转载地址:http://rrews.baihongyu.com/

你可能感兴趣的文章
C#修改JPG图片EXIF信息中的GPS信息
查看>>
从零开始的Docker ELK+Filebeat 6.4.0日志管理
查看>>
Sequelize的原始查询的时区问题
查看>>
How it works(1) winston3源码阅读(A)
查看>>
How it works(2) autocannon源码阅读(A)
查看>>
How it works(3) Tilestrata源码阅读(A)
查看>>
How it works(12) Tileserver-GL源码阅读(A) 服务的初始化
查看>>
uni-app 全局变量的几种实现方式
查看>>
echarts 为例讲解 uni-app 如何引用 npm 第三方库
查看>>
uni-app跨页面、跨组件通讯
查看>>
springmvc-helloworld(idea)
查看>>
JDK下载(百度网盘)
查看>>
idea用得溜,代码才能码得快
查看>>
一篇掌握python魔法方法详解
查看>>
数据结构和算法5-非线性-树
查看>>
数据结构和算法6-非线性-图
查看>>
数据结构和算法7-搜索
查看>>
数据结构和算法8-排序
查看>>
windows缺少dll解决办法
查看>>
JPA多条件动态查询
查看>>