JAVA学习——多线程
2015-09-05 11:12
633 查看
多线程就是指一个应用程序中有多条并发执行的线索,每条线索都被称作一个线程,他们会交替执行。
在实现方式上,主要有两种:
1.继承Thread类
2.实现Runnable接口
继承Thread类
此处我们模拟窗口售票程序,以便为后面比较两种实现方式
测试结果如图:
实现Runnable接口
测试结果如图:
从运行结果可以看出,继承Thread类时,每张票都被打印了2次,出现这种现象,说明2个线程没有共享5张票,而是各自出了5张
从代码也可以看出,继承Thread类时,创建了两个TicketsWindow对象,每个线程各自独立运行,互不干扰。
而实现Runnable接口,只创建了一个TicketsWindow对象,然后创建两个线程,每个线程在调用时,都去调用TicketsWindow对象的run()方法,这样就可以保证线程在访问的时候是同一个tickets变量,共享5张票
实现Runnable接口相比较继承Thread类的优势:
1、适合多个线程处理同一资源
2、可以避免java的单继承
PS:大部分应用程序在设计的时候,大多采用第二种方式来创建多线程,即实现Runnable接口
后台线程
对java程序来说,只要还有一个前台线程在运行,这个进程就不会结束,如果一个进程中只有后台线程运行,这个进程就会结束。
调用setDaemon(true)方法,使线程变成一个后台线程
注意:将线程设置为后台线程,一定要在未启动之前设置,也就是说setDaemon(true)方法要在start()方法前调用,否则会出现java.lang.IllegalThreadStateException异常
线程的优先级
通过Thread类的setPriority(int newPriority)方法对其进行设置,该方法的参数newPriority接收的是1~10的整数,或三个Thread类的静态常量。
线程的休眠
可以人为的控制线程,使正在执行的线程暂停,将CPU让给其它线程。
调用静态方法sleep(long millis)
测试结果为:每隔2秒输出一行
线程一正在输出:1
线程一正在输出:2
线程一正在输出:3
线程一正在输出:4
线程一正在输出:5
线程插队
在现实生活中,经常会遇到插队的现象,而在Thread里面,也提供了一个join()方法来实现这个“功能”。
在调用join()方法的线程要执行完之后,其他进程才能继续执行。
main正在输出:0
线程一正在输出:0
线程一正在输出:1
main正在输出:1
main正在输出:2
线程一正在输出:2
线程一正在输出:3
线程一正在输出:4
main正在输出:3
main正在输出:4
线程的同步:
传送门:http://blog.csdn.net/u012482299/article/details/48226661
在实现方式上,主要有两种:
1.继承Thread类
2.实现Runnable接口
继承Thread类
此处我们模拟窗口售票程序,以便为后面比较两种实现方式
/** * 模拟窗口售票 * 继承Thread类,实现多线程, * @author Shawn·Zhang */ public class Example01 { public static void main(String[] args) { new TicketWindow().start();//创建一个线程对象TicketWindow并开启 new TicketWindow().start();//创建一个线程对象TicketWindow并开启 } } class TicketWindow extends Thread { private int tickets = 5; @Override public void run() { while (true) {//通过死循环打印 if (tickets > 0) { System.out.println(Thread.currentThread().getName() + "正在发售第" + tickets-- + "张票"); } } } }
测试结果如图:
实现Runnable接口
/** * 模拟窗口售票 * 实现Runnable接口,实现多线程, * @author Shawn·Zhang */ public class Example02 { public static void main(String[] args) { TicketWindow tw = new TicketWindow();//创建TicketWindow实例对象tw new Thread(tw).start();//创建线程,并开启 new Thread(tw).start();//创建线程,并开启 } } class TicketWindow implements Runnable { private int tickets = 5; @Override public void run() { while (true) {//通过死循环打印输出语句 if (tickets > 0) { System.out.println(Thread.currentThread().getName() + "正在发售第" + tickets-- + "张票"); } } } }
测试结果如图:
从运行结果可以看出,继承Thread类时,每张票都被打印了2次,出现这种现象,说明2个线程没有共享5张票,而是各自出了5张
从代码也可以看出,继承Thread类时,创建了两个TicketsWindow对象,每个线程各自独立运行,互不干扰。
而实现Runnable接口,只创建了一个TicketsWindow对象,然后创建两个线程,每个线程在调用时,都去调用TicketsWindow对象的run()方法,这样就可以保证线程在访问的时候是同一个tickets变量,共享5张票
实现Runnable接口相比较继承Thread类的优势:
1、适合多个线程处理同一资源
2、可以避免java的单继承
PS:大部分应用程序在设计的时候,大多采用第二种方式来创建多线程,即实现Runnable接口
后台线程
对java程序来说,只要还有一个前台线程在运行,这个进程就不会结束,如果一个进程中只有后台线程运行,这个进程就会结束。
调用setDaemon(true)方法,使线程变成一个后台线程
/** * 后台线程 * @author Shawn·Zhang * */ public class Example03 { public static void main(String[] args) { DaemonThread dt = new DaemonThread();//创建dt对象,并实例化 Thread t = new Thread(dt,"t线程");//创建线程t,并共享dt资源 System.out.println("t线程默认是后台线程吗?"+Thread.currentThread().isDaemon());//判断是否默认后台线程 t.setDaemon(true);//将t线程设置为后台线程 t.start();//启动线程 } } class DaemonThread implements Runnable{//创建DaemonThread类,实现runnable接口 @Override public void run() {//重写run()方法 System.out.println(Thread.currentThread().getName()+"正在运行"); } }从结果可以看出,虽然是死循环,但程序还是可以运行完毕,这是因为操作的线程已经是后台线程了
注意:将线程设置为后台线程,一定要在未启动之前设置,也就是说setDaemon(true)方法要在start()方法前调用,否则会出现java.lang.IllegalThreadStateException异常
线程的优先级
通过Thread类的setPriority(int newPriority)方法对其进行设置,该方法的参数newPriority接收的是1~10的整数,或三个Thread类的静态常量。
Thread类的静态常量 | 功能描述 |
static int MAX_PRIORITY | 表示线程的最高优先级,相当于值10 |
static int MIN_PRIORITY | 表示线程的最低优先级,相当于值1 |
static int NORM_PRIORITY | 表示线程的普通优先级,相当于值5 |
可以人为的控制线程,使正在执行的线程暂停,将CPU让给其它线程。
调用静态方法sleep(long millis)
/** * 线程休眠 * @author Shawn·Zhang */ public class Example04 { public static void main(String[] args) throws Exception { new Thread(new SleepThread()).start();//创建线程 } } class SleepThread implements Runnable { @Override public void run() { for (int i = 1; i <= 5; i++) { try { Thread.sleep(2000);//当前线程休眠2秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程一正在输出:" + i); } } }
测试结果为:每隔2秒输出一行
线程一正在输出:1
线程一正在输出:2
线程一正在输出:3
线程一正在输出:4
线程一正在输出:5
线程插队
在现实生活中,经常会遇到插队的现象,而在Thread里面,也提供了一个join()方法来实现这个“功能”。
在调用join()方法的线程要执行完之后,其他进程才能继续执行。
/** * 线程插队 * @author Shawn·Zhang */ public class Example05 { public static void main(String[] args) throws Exception { Thread t = new Thread(new MyThread(), "线程一"); t.start(); for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + "正在输出:" + i); if ( 9f16 i == 2) { t.join(); } Thread.sleep(500); } } } class MyThread implements Runnable { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + "正在输出:" + i); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }执行结果如下:
main正在输出:0
线程一正在输出:0
线程一正在输出:1
main正在输出:1
main正在输出:2
线程一正在输出:2
线程一正在输出:3
线程一正在输出:4
main正在输出:3
main正在输出:4
线程的同步:
传送门:http://blog.csdn.net/u012482299/article/details/48226661
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- C#实现多线程的同步方法实例分析
- 浅谈chuck-lua中的多线程
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#多线程学习之(六)互斥对象用法实例
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- C#控制台下测试多线程的方法
- Ruby 多线程的潜力和弱点分析
- C#中WPF使用多线程调用窗体组件的方法
- C#如何对多线程、多任务管理(demo)
- C#实现多线程的Web代理服务器实例
- c#实现多线程局域网聊天系统
- PHP使用CURL实现多线程抓取网页
- 浅解关于C#多线程的介绍
- 批处理程序中的“多线程”处理代码