12-23java面向对象之多线程
2014-12-24 15:24
706 查看
1.多线程的概念
几乎所有的操作系统都支持同时运行多个任务,每一个任务通常就是一个程序,每个运行的程序就是一个进程。当一个程序运行是,内部可能包含了多个顺序执行流,每个执行流就是线程。继承的特点:并发性。多个进程可以在单个处理器上并发执行,不会相互影响,
2.java多线程的实现
2.1继承Thread类
在java.lang包中定义了Thread类,继承该类之后,必须覆写run()方法.启动该线程,必须调用Thread类中的start()方法,但是该方法最终还是调用的run()方法。
class MyThread extends Thread // 继承Thread类 { private String name ; public MyThread(String name) // 构造方法 { this.name = name ; } public void run() // 覆写run方法 { for (int i =0;i<10 ;++i ) { System.out.println(this.name + "运行,i=" + i); } } } public class TestThread1 { public static void main(String[] args) { MyThread mt1 = new MyThread("线程1") ; MyThread mt2 = new MyThread("线程2") ; mt1.run(); mt2.run(); } }
运行结果发现:并没有并发执行效果,所以要修改程序。必须使用start()方法来启动线程。
class MyThread extends Thread // 继承Thread类 { private String name ; public MyThread(String name) // 构造方法 { this.name = name ; } public void run() // 覆写run方法 { for (int i =0;i<10 ;++i ) { System.out.println(this.name + "运行,i=" + i); } } } public class TestThread2 { public static void main(String[] args) { MyThread mt1 = new MyThread("线程1") ; // 创建对象 MyThread mt2 = new MyThread("线程2") ; mt1.start(); mt2.start(); } }
程序运行总是并发执行不同的线程。那个线程先抢占到CPU资源就执行它。
如果线程已经启用了,再次调用start方法会出现异常。
class MyThread extends Thread // 继承Thread类 { private String name ; public MyThread(String name) // 构造方法 { this.name = name ; } public void run() // 覆写run方法 { for (int i =0;i<10 ;++i ) { System.out.println(this.name + "运行,i=" + i); } } } public class TestThread3 { public static void main(String[] args) { MyThread mt1 = new MyThread("线程1") ; // 创建对象 mt1.start(); mt1.start(); } }
提示错误信息;
Exception in thread "main" java.lang.IllegalThreadStateException at java.lang.Thread.start(Unknown Source) at TestThread3.main(TestThread3.java:22) |
2.2实现Runnable接口
Runnable接口中只定义了run()方法,所以也需要覆写该方法。它之中并没有start()方法,但是在Thread的构造方法中有这么一个接收Runnable实例的,用他作为启动线程的操作。Thread public Thread(Runnable target) class MyThread implements Runnable // 继承Thread类 { private String name ; public MyThread(String name) // 构造方法 { this.name = name ; } public void run() // 覆写run方法 { for (int i =0;i<10 ;++i ) { System.out.println(this.name + "运行,i=" + i); } } } public class TestThread4 { public static void main(String[] args) { Runnable r1 = new MyThread("线程1") ; // 向上转换实现接口 Runnable r2 = new MyThread("线程2") ; // 向上转换实现接口 Thread mt1 = new Thread(r1); Thread mt2 = new Thread(r2); mt1.start(); mt2.start(); } }
执行结果:完成了多线程的功能。
2.3联系与区别
联系:定一个是Thread也是Runnable的实现,这个就是之前的代理设计。All Implemented Interfaces: Runnable |
使用Runnable优点:
1、适合多个相同程序代码的多线程处理同一个资源
2、避免单继承
3、增强健壮性
下面验证共享;
//本程序验证共享属性 class MyThread extends Thread { private int ticket = 5; // 定义属性有5个 public void run() // 覆写run方法 { for (int i =0;i<10 ;++i ) { if (ticket > 0) { System.out.println("卖出门票ticket =" + ticket--); } } } } public class TestThread6 { public static void main(String[] args) { Thread mt1 = new MyThread(); Thread mt2 = new MyThread(); mt1.start(); mt2.start(); } }
这个时候发现,每个线程都各卖个的,没有到达资源共享。
//本程序验证共享属性 class MyThread implements Runnable // 实现Runnable接口 { private int ticket = 5; // 定义属性有5个 public void run() // 覆写run方法 { for (int i =0;i<10 ;++i ) { if (ticket > 0) { System.out.println("卖出门票ticket =" + ticket--); } } } } public class TestThread5 { public static void main(String[] args) { Runnable r1 = new MyThread() ; // 向上转换实现接口 Thread mt1 = new Thread(r1); Thread mt2 = new Thread(r1); mt1.start(); mt2.start(); } }
3.线程的状态
调用了start也不会立即启动,需要等待CPU。4.线程的操作方法
对线程的操作都在Thread类中。4.1取得和设置线程名称
在Thread类的构造方法中有一个名称的参数,同时具有方法setName()和getName()可以分别设置和获取名称。线程名称可以相同,在运行时候可以修改。Public static Thead currentThread()方法返回当前的线程。
//本程序测试线程名称 class MyThread implements Runnable { public void run() // 覆写run方法 { for (int i =0;i<10 ;++i ) { System.out.println(Thread.currentThread().getName() +"当前线程名称是—"+ i); } } } public class TestThread7 { public static void main(String[] args) { Runnable mt1 = new MyThread(); Runnable mt2 = new MyThread(); Thread t1 = new Thread(mt1); //系统自动命名 Thread t2 = new Thread(mt2,"线程A"); //手动命名 t1.start() ; t2.start(); } }
运行发现,线程设置名称之后会按照设置名称自动运行,没有设置名称的按照格式Thread-0 依次编号,实际上肯定存在static属性,用于记录产生对象的个数。
4.2取得当前线程
public static Thread currentThread() Returns a reference to the currently executing thread object. |
//本程序测试线程名称 class MyThread implements Runnable { public void run() // 覆写run方法 { for (int i =0;i<10 ;++i ) { System.out.println(Thread.currentThread().getName() +"当前线程名称是—"+ i); } } } public class TestThread8 { public static void main(String[] args) { Runnable mt2 = new MyThread(); Thread t2 = new Thread(mt2,"线程A"); //手动命名 t2.start(); t2.run(); } }
此时程序中由主方法直接调用线程的run方法,此时main是由“t2.run();”产生的。
Java程序在启动的时候至少有两个线程。JVM运行的时候启动了一个线程,在资源管理器中能够看到,同时后台还有垃圾收集GC线程。
4.3判断线程是否在执行
public final boolean isAlive() //本程序测试线程名称 class MyThread implements Runnable { public void run() // 覆写run方法 { for (int i =0;i<3 ;++i ) { System.out.println("当前线程名称是—"+Thread.currentThread().getName() + i); } } } public class TestThread9 { public static void main(String[] args) { Runnable mt2 = new MyThread(); Thread t2 = new Thread(mt2,"线程A"); //手动命名 System.out.println("线程启动之前->" + t2.isAlive()); t2.start(); System.out.println("线程启动之后->" + t2.isAlive()); for (int i= 1;i<10 ;++i ) { System.out.println(t2.isAlive()); } System.out.println("代码执行之后->" + t2.isAlive()); } }
由于此时在线程A和主方法中执行次序不确定,所以结果不同。
4.4线程强制运行
public final void join() throws InterruptedException Waits for this thread to die. |
//本程序测试线程名称 class MyThread implements Runnable { public void run() // 覆写run方法 { for (int i =0;i<40 ;++i ) { System.out.println("当前线程名称是—"+ Thread.currentThread().getName() + i); } } } public class TestThread10 { public static void main(String[] args) { Runnable mt1 = new MyThread(); Thread t1 = new Thread(mt1,"线程A"); //手动命名 t1.start(); for (int i =0;i<40 ;++i ) { if (i>10) { try { t1.join(); } catch (InterruptedException e) { } } System.out.println("main运行" + i); } } }
当main运行到10之后,都是由主线程占用。
4.5线程的休眠
public static void sleep(long millis) 使用类名称调用,类似current throws InterruptedException |
//本程序测试线程名称 class MyThread implements Runnable { public void run() // 覆写run方法 { for (int i =0;i<10 ;++i ) { try { Thread.sleep(2000); // 每2s产生一个输出 } catch (InterruptedException e) { } System.out.println("当前线程名称是—"+ Thread.currentThread().getName() + i); } } } public class TestThread11 { public static void main(String[] args) { Runnable mt1 = new MyThread(); Thread t1 = new Thread(mt1,"线程A"); //手动命名 t1.start(); } }
4.6线程强制中断
当一个线程正在运行时,另一个线程可以使用interrupt方法中断其运行。public void interrupt() Interrupts this thread. |
//本程序测试线程名称 class MyThread implements Runnable { public void run() // 覆写run方法 { System.out.println("1.进入run方法"); try { Thread.sleep(5000); // 休眠5s System.out.println("2.休眠结束"); } catch (InterruptedException e) { System.out.println("3.休眠中断"); return ; // 返回调用处 } System.out.println("4.run正常结束"); } } public class TestThread12 { public static void main(String[] args) { Runnable mt1 = new MyThread(); Thread t1 = new Thread(mt1,"线程A"); //手动命名 t1.start(); try //作用是延时 { Thread.sleep(2000); } catch (InterruptedException e) {} t1.interrupt(); } }
4.7后台线程
一个线程在运行,整个java进程不会消失。可以设置后台线程,哪怕进程结束了,线程还在。public final void setDaemon(boolean on) |
class MyThread implements Runnable { public void run() // 覆写run方法 { while (true) { System.out.println(Thread.currentThread().getName() + "在运行"); } } } public class TestThread13 { public static void main(String[] args) { Runnable mt1 = new MyThread(); Thread t1 = new Thread(mt1,"线程A"); //手动命名 t1.start(); t1.setDaemon(true); } }
4.8优先级设置
public final void setPriority(int newPriority) Changes the priority of this thread. |
<p>注意:主方法的优先级是<span style="font-family:Times New Roman;">5</span></p><h2>4.9<span style="font-family:黑体;">线程的礼让</span></h2><table><tbody><tr><td valign="top"><p>public static void yield()</p><p>Causes the currently executing thread object to temporarily pause and allow other threads to execute.</p></td></tr></tbody></table>class MyThread implements Runnable { public void run() // 覆写run方法 { for (int i=0;i<3 ;++i ) { try { Thread.sleep(1000); System.out.println("正在运行的是: " + Thread.currentThread().getName() + i); } catch (InterruptedException e){} } } } public class TestThread14 { public static void main(String[] args) { Runnable mt1 = new MyThread(); Thread t1 = new Thread(mt1,"线程A"); //手动命名 Runnable mt2 = new MyThread(); Thread t2 = new Thread(mt2,"线程B"); //手动命名 Runnable mt3 = new MyThread(); Thread t3 = new Thread(mt3,"线程C"); //手动命名 t1.setPriority(Thread.MAX_PRIORITY); //设置优先级 t2.setPriority(Thread.MIN_PRIORITY); t3.setPriority(Thread.NORM_PRIORITY); t1.start(); t2.start(); t3.start(); } }
注意:主方法的优先级是5
4.9线程的礼让
public static void yield() Causes the currently executing thread object to temporarily pause and allow other threads to execute. |
class MyThread implements Runnable { public void run() // 覆写run方法 { for (int i=0;i<5 ;++i ) { System.out.println("正在运行的是: " + Thread.currentThread().getName() + i); if (i ==3) { System.out.println("线程礼让"); Thread.currentThread().yield(); } } } } public class TestThread15 { public static void main(String[] args) { Runnable mt1 = new MyThread(); Thread t1 = new Thread(mt1,"线程A"); //手动命名 Runnable mt2 = new MyThread(); Thread t2 = new Thread(mt2,"线程B"); //手动命名 t1.start(); t2.start(); } }
祝大家健健康康,快快乐乐。
相关文章推荐
- JAVA笔记四(12-15 面向对象基础)
- 12-5Java面向对象笔记(一)
- java学习之旅39--面向对象_12_继承_方法的重写
- 【学习笔记12】java面向对象-多态
- 【java面向对象下:多线程编程】
- 12-21java面向对象之异常
- JavaSE入门学习23:Java面向对象之构造方法
- 12-24java面向对象之同步和死锁
- 黑马程序员学习log第四篇基础知识:JAVA的面向对象之多线程总结
- 12-15java面向对象之多态性操作
- 12-6java面向对象之String类常用方法的总结
- java学习日记_12:面向对象之如何使用类
- 黑马程序员——第十一天(Java面向对象-多线程一)
- java面向对象12讲 基础一 什么是面向对象
- 12-9java面向对象之链表操作
- 12-11java面向对象之内部类操作
- JavaSE入门学习23:Java面向对象之构造方法
- java学习日记_23:面向对象之对两种类的赋值方式的比较
- Java基础(极客)——12、Java面向对象基本特征:继承
- 12-22java面向对象之package & import