多线程

来源:互联网 发布:十大网络写手 编辑:程序博客网 时间:2024/06/07 06:24

线程和进程
进程:独立执行的一个程序称为进程。
线程:进程中的一个单一的连续控制流程,不能独立运行,一个进程可以拥有一个或多个线程,当一个进程拥有多个线程的时候称之为多线程。

单线程程序与多线程程序
单线程程序:程序只有一个线程顺序执行。
多线程程序:程序有多个线程并发执行。

Java对多线程的支持
Java在语言级提供了对多线程程序设计的支持。
实现多线程程序的两种方式:
    (1)从Thread类继承;
    (2)实现Runnable接口。

继承Thread类的实现方式:
class MyThread extends Thread{
 public void run(){
  System.out.println("线程运行了.");
 }
}
public class MultiThread {
 public static void main(String[] args){
  MyThread mt=new MyThread();  //生成一个线程的对象
  mt.start();  //用start方法启动线程
  System.out.println("main方法运行了.");
 }
}

实现Runnable接口的实现方式:
class MyThread implements Runnable{
 public void run(){
  System.out.println("线程运行了.");
 }
}
public class MultiThread {
 public static void main(String[] args){
  MyThread mt=new MyThread();  //生成一个线程的对象
  Thread t=new Thread(mt);  //还是需要用Thread类创建线程
  t.start();  //启动线程
  System.out.println("main方法运行了.");
 }
}

两种实现方式的比较
继承Thread类,该类将不能继承其它类,每个线程拥有自己的对象。
     MyThread mt1=new MyThread();
     MyThread mt2=new MyThread();
     t1.start();
     t2.start();

实现Runnable接口,该类还能继承其它类,每个线程可以共享一个对象。
     MyThread mt=new MyThread();
 Thread t1=new Thread(mt);
 Thread t2=new Thread(mt);
 t1.start();
 t2.start();
守护线程
通过前面的例子可以知道,主线程和其他线程的执行是并行的,互不干扰的,即一个线程的终止和其他线程没有关系,当你想让其他线程在主线程结束的时候也跟着结束,可以将该线程设置为守护线程。
     MyThread mt=new MyThread();
 Thread t1=new Thread(mt);
 t1.setDaemon(true);    //使用setDaemon方法将线程设为守护线程
 //start方法必须在setDaemon方法后面调用,否则设置无效
     t1.start();   
     System.out.println(t1.isDaemon());    //查看该线程是否为守护线程

join()和yield()
如果有一个线程A正在运行,你希望插入另一个线程并要求插入的线程执行完毕之后再执行线程A,可以使用join()方法来完成这个需求,就好像你手头上正有一个工作在进行,老板插入一个工作要求你先作好,然后再进行原先的工作。

如果有两个线程A和B,当A调用了yield()方法后,线程A将放弃当前的执行机会,让线程B执行,直到线程A下次有机会的时候再执行。

线程常用方法

方法          说明
start()  启动线程
isAlive()  线程是否还活着(Runnable、Running、Blocked)
static?void sleep(long?m) 使当前的线程睡m个毫秒
getPriority () 得到线程的优先级
setPriority (int?newP)  设置线程的优先级
static?void yield()  让出CPU,当前线程进入就绪等待队列
wait() 等待某个信号或事件,进入blocked状态,
notify()、notityAll() 唤醒某个执行了wait()的线程;
                        唤醒所有执行了wait()的线程

线程的状态
创建状态(New)  执行下列语句时,线程就处于创建状态: MyThread mt = new MyThread ( ); 当一个线程处于创建状态时,它仅仅是一个空的线程对象,系统
   不为它分配资源。

 2.可运行状态( Runnable )   mt.start( );当一个线程处于可运行状态时,系统为这个线程分配了它需的系
     统资源,安排其运行并调用线程运行方法,这样就使得该线程处于可运行( Runnable )状态。需要注意的是这一状态并不是运行中状态(Running ),因为线程也许实际上并未真正运行。由于很多计算机都是单处理器的,所以要在同一时刻运行所有的处于可运行状态的线程是不可能的,Java的运行系统必须实现调度来保证这些线程共享处理器。
3.阻塞状态(Not Runnable)  进入不可运行状态的原因有如下几条:   1) 调用了sleep()方法;
       2) 为等候一个条件变量,线程调用wait()方法;   3) 输入输出流中发生线程阻塞;  因为某种原因(输入/输出、等待消息或其它阻塞情况),系统不能执行线程的状态。这时即使处理器空闲,也不能执行该线程。

4. 死亡状态(Dead) 线程的终止一般可通过两种方法实现:自然撤消(线程执行完)或是被停止(调用stop()方法)。目前不推荐通过调用stop()来终止线程的执行(随意的stop会导致资源没有释放)而是让线程执行完。

线程的同步
原因:当多个线程对一个资源进行访问时,需要对线程进行同步,否则可能出现错误的数据。例如,火车站的售票系统就采用了线程的同步,因为火车票的数量是固定的,每个售票窗口相当于一个线程,在售票过程中,不能将一张票卖出去两次。
同步需要用到的关键字:synchronized
同步的两种方式:同步块和同步方法
每一个对象都有一个监视器,或者叫做锁。
同步方法利用的是this所代表的对象的锁。

线程的死锁
线程1锁住了对象A的监视器,等待对象B的监视器,线程2锁住了对象B的监视器,等待对象A的监视器,就造成了死锁。
wait、notify、notifyAll
每一个对象除了有一个锁之外,还有一个等待队列(wait set),当一个对象刚创建的时候,它的等待队列是空的。
我们应该在当前线程锁住对象的锁后,去调用该对象的wait方法。
当调用对象的notify方法时,将从该对象的等待队列中删除一个任意选择的线程,这个线程将再次成为可运行的线程。
当调用对象的notifyAll方法时,将从该对象的等待队列中删除所有等待的线程,这些线程将成为可运行的线程。
wait和notify主要用于producer-consumer(生产者-消费者)这种关系中。
线程的终止
设置一个flag变量。
结合interrupt()方法。


原创粉丝点击