Java-多线程
2016-03-11 10:35
549 查看
一、进程和线程
多进程:在操作系统中可以同时运行多个运用程序。多线程:在同一个运用程序中可以有多个执行的路径。
进程和线程的区别:
进程是系统资源调度和分配的基本单位,线程是CPU调度和分配的基本单位。
一个线程只能属于一个进程,一个进程可以拥有多个线程,但是至少有一个线程(称为主线程,Android系统中也称为UI线程)。
进程之间不能共享内存,线程之间可以共享内存,但是在线程之间通信需要注意数据同步的问题。
二、线程
1、创建多线程
创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("MyThread1:" + i); } } } MyThread thread = new MyThread(); thread.start();
另一个方法是:3. 声明一个实现Runnable接口的子类,重写run()方法。使用的时候,声明一个Thread类的实例,把Runnable的子类对象传入就可以了。
class MyThread2 implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("MyThread2:"+i); } } } MyThread2 thread2 = new MyThread2(); new Thread(thread2).start();
在创建线程的时候可以传入一个指定线程名称的参数,如果没有指定线程名,则会默认一个线程名称为”Thread-0”(0表示子线程的数量,从0开始计数)。
问题:继承Thread类和实现Runnable接口的区别?
(1)实现Runnable接口可以解决单继承的局限问题;
(2)方便解决多个线程操作同一个数据的问题。
2、多线程的优先级
每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程,所以对执行结果会有一定的影响。public final static int MIN_PRIORITY = 1;//最低优先级 public final static int NORM_PRIORITY = 5;//正常优先级 public final static int MAX_PRIORITY = 10;//最大优先级
3、常用方法
public static Thread currentThread();//返回对当前正在执行的线程对象的引用。 public long getId();//返回该线程的标识符。线程 ID 是一个正的 long 数,在创建该线程时生成。线程 ID 是唯一的,并终生不变。 public final void setName(String name);//改变线程名称,使之与参数 name 相同 public final String getName();//返回该线程的名称 public final void setPriority(int newPriority);//更改线程的优先级。 public final int getPriority();//返回线程的优先级。 public final ThreadGroup getThreadGroup();//返回该线程所属的线程组。 如果该线程已经终止(停止运行),该方法则返回 null。 public final void join();//等待该线程终止。 public final void join(long millis);//等待该线程终止的时间最长为 millis 毫秒。 public final void join(long millis,int nanos);//等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。 join:插队。如果A线程要礼让B线程,需要在A线程中去调用B线程的join方法,才会起到插队的效果(主线程和子线程同时运行,满足一定条件后,让子线程先运行)。 public static void sleep(long millis); public static void sleep(long millis,int nanos);//在指定的时间内让当前正在执行的线程休眠(暂停执行),该线程处于阻塞状态。 public static void yield();//暂停当前正在执行的线程对象,并执行其他线程。 Yield()方法是停止当前线程,让同等优先权的线程运行,如果没有同等优先权的线程,那么Yield()方法将不会起作用。 public final void setDaemon(boolean on);//将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时(没有了被守护者),Java 虚拟机退出。 该方法必须在启动线程前调用。 所谓守护线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者。 public final boolean isDaemon();//测试该线程是否为守护线程 public String toString();//返回该线程的字符串表示形式,包括线程名称、优先级和线程组。 public void start();//使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 //结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法)。 public void run();//如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。 public final void stop();//(已过时)强迫线程停止执行。 public void interrupt();//中断线程 interrupt()中断线程。需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。 对某一线程调用interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。 但是,一旦该线程进入到wait()/sleep()/join()后,就会立刻抛出InterruptedException public static boolean interrupted();//测试当前线程是否已经中断 public boolean isInterrupted();//测试线程是否已经中断 public final void wait(long timeout) public final void wait(long timeout,int nanos) public final void wait();//在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 public final void notify();//唤醒在此对象监视器上等待的单个线程。 public final void notifyAll();//唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait 方法,在对象的监视器上等待
例:设置线程的优先级,高优先级的线程会优先执行。
public class PriorityTest { public static void main(String[] args) { PriorityThread t1 = new PriorityThread("张三"); PriorityThread t2 = new PriorityThread("李四"); t1.start(); t2.start(); System.out.println(t1.getPriority()+":"+t2.getPriority()); t1.setPriority(Thread.MAX_PRIORITY); t2.setPriority(Thread.MIN_PRIORITY); System.out.println(t1.getPriority()+":"+t2.getPriority()); } } class PriorityThread extends Thread { private String threadName; public PriorityThread(String threadName){ super(threadName); } @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+":" + i); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public String getThreadName() { return threadName; } public void setThreadName(String threadName) { this.threadName = threadName; } }
输出结果:
张三:0 李四:0 设置前:t1=5:t2=5 设置后:t1=10:t2=1 张三:1 李四:1 张三:2 李四:2 李四:3 张三:3 张三:4 李四:4
结果可以看出线程”张三”比线程”李四”更优先执行
例:Sleep()休眠一段时间
public class SleepTest { public static void main(String[] args) { TimeThread t1 = new TimeThread(); TimeThread t2 = new TimeThread(); t1.start(); t2.start(); } } class TimeThread extends Thread{ @Override public void run() { while(true){ System.out.println(Thread.currentThread().getName()+":"+new Date()); try { sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
输出结果:
Thread-0:Wed Mar 16 22:08:33 CST 2016 Thread-1:Wed Mar 16 22:08:33 CST 2016 Thread-0:Wed Mar 16 22:08:34 CST 2016 Thread-1:Wed Mar 16 22:08:34 CST 2016 Thread-0:Wed Mar 16 22:08:35 CST 2016 Thread-1:Wed Mar 16 22:08:35 CST 2016 Thread-0:Wed Mar 16 22:08:36 CST 2016 Thread-1:Wed Mar 16 22:08:36 CST 2016
每个1s执行一次线程
例:Join,主线程礼让子线程
public class JoinTest { public static void main(String[] args) { JoinThread t1 = new JoinThread(); t1.start(); for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); if (i == 2) { try { t1.join();//t1子线程优先执行完后,再执行主线程 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } class JoinThread extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(getName() + ":" + i); } } }
输出结果:
main:0 main:1 main:2 Thread-0:0 Thread-0:1 Thread-0:2 Thread-0:3 Thread-0:4 Thread-0:5 Thread-0:6 Thread-0:7 Thread-0:8 Thread-0:9 main:3 main:4 main:5 main:6 main:7 main:8 main:9
当主线程中i的值为2时,子线程优先执行完,然后再继续执行主线程
例:interrupt中断线程,线程进入到wait()/sleep()/join()后,会抛出interruptexception异常。
public class InterruptTest2 { public static void main(String[] args) { InterruptThread2 t = new InterruptThread2(); t.start(); t.interrupt(); } } class InterruptThread2 extends Thread { @Override public void run() { System.out.println("开始"); System.out.println("ok"); try { sleep(1000); } catch (InterruptedException e) { System.out.println("出现异常"); e.printStackTrace(); } System.out.println("结束"); } }
输出结果:
开始 ok 出现异常 结束 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.thread.InterruptThread2.run(InterruptTest2.java:19)
如果需要中断线程,一般设置一个标志位,在要中断的线程中改变这个标志位。
public class InterruptTest { public static void main(String[] args) { InterruptThread t = new InterruptThread(); t.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } t.setStop(false);// // t.interrupt(); } } class InterruptThread extends Thread { private boolean flag = true; @Override public void run() { while (flag) { System.out.println("ok"); } } public void setStop(boolean flag) { this.flag = flag; } }
关于线程的几个常用方法的使用,参考链接:
http://zheng12tian.iteye.com/blog/1233638
4、线程的生命周期
a) 新建状态
i. 在程序中用构造方法创建了一个线程对象后,新的线程对象便处于新建状态,此时,它已经有了相应的内存空间和其它资源,但还处于不可运行状态。新建一个线程对象可采用线程构造方法来实现。
ii. 例如:Thread thread=new Thread();
b) 就绪状态
i. 新建线程对象后,调用该线程的start()方法就可以启动线程。当线程启动时,线程进入就绪状态。此时,线程将进入线程队列排队,等待CPU调用,这表明它已经具备了运行条件。
c) 运行状态
i. 当就绪状态的线程被调用并获得处理器资源时,线程就进入了运行状态。此时,自动调用该线程对象的run()方法。run()方法定义了该线程的操作和功能。
d) 阻塞状态
i. 一个正在执行的线程在某些特殊情况下,如被人为挂起,将让出CPU并暂时中止自己的执行,进入阻塞状态。在可执行状态下,如果调用sleep(2000)、wait()等方法,线程都将进入阻塞状态。阻塞时,线程不能进入排队队列,只有当引起阻塞的原因被消除后,线程才可以转入就绪状态。
e) 死亡状态
i. 线程调用stop()方法时或run()方法执行结束后,线程即处于死亡状态。处于死亡状态的线程不具有继续运行的能力。//线程池 可以让线程起死回生
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法