Java多线程学习笔记

原创 2013年12月01日 22:04:01

Java多线程学习笔记

1.线程的概念
    操作系统可以运行多个进程(Process),每一个进程又可以创建多个线程(Thread).
    操作系统启动一个程序时,先在系统中建立一个进程,接着在这个进程中至少建立一个线程(主线程)作为程序运行的入口点,线程是依附于进程而存在的,并且至少包含一个主线程。
    线程和进程一样,也有创建、销毁和切换等状态,但负荷远小于进程,称为轻量级进程.
    线程可以共享进程的内存,并且还有一个属于自己的内存空间(称为线程栈),是在建立线程时由系统分配的,主要用来保存线程内部使用的数据。

2.线程的状态
    (1)New(新建)
    (2)Runnable(可运行、就绪)
    (3)Running(运行)
    (4)Blocked(被阻塞、挂起)
    (5)Dead(死亡)

3.线程类Thread常用方法
    run()               线程运行时所执行的代码,子类必须通过覆盖该方法来实现自己的功能。
    start()             启动线程
    sleep(long milis)   休眠,时间单位毫秒
    interrupt()         中断线程
    interrupted()       判断当前线程是否被中断(会清除中断状态标记)
    isInterrupted()     判断指定线程是否被中断
    isAlive()           判断线程是否处于活动状态(已调用start,但run还未返回)
    currentThread()     返回当前线程对象的引用.
    setName(String threadName)   设置线程的名字
    getName()           获取线程的名字,返回线程的名字
    join([long milis[,int nanos]])   连接线程,加入线程,须等待加入的线程执行完
    destroy()           销毁线程
    yield()             暂停当前线程,让其他线程执行
    setPriority(int p)  设置线程的优先级
    notify()
    notifyAll()
    wait()

4.使用继承线程类Thread创建线程
    使用线程的注意点: 编写线程执行的方法(run()方法),启动线程(start()方法)
    线程类Thread是在包java.lang中定义的.
    示例:
public class ThreadTest1 extends Thread{
 String threadName;
 
 public ThreadTest1(String threadName){
  System.out.println("初始化线程:" + threadName);
  this.threadName = threadName;
  
 }
 
 //线程运行时执行的代码
 public void run(){
  for(int i=0; i<3; i++){
   System.out.println("正在运行线程" + threadName);
   try {
    Thread.sleep(3);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }   
  }
 }
 
 public static void main(String[] args){
  System.out.println("开始线程测试");
  ThreadTest1 thread1 = new ThreadTest1("线程1");
  ThreadTest1 thread2 = new ThreadTest1("线程2");
  ThreadTest1 thread3 = new ThreadTest1("线程3");
  
  thread1.start();  //启动线程
  thread2.start();  //启动线程  
  thread3.start();  //启动线程
  
  thread2.setPriority(MAX_PRIORITY); //设置线程优先级
  
  System.out.println("结束线程测试");
 }
}
运行结果:
开始线程测试
初始化线程:线程1
初始化线程:线程2
初始化线程:线程3
正在运行线程线程2
正在运行线程线程3
结束线程测试
正在运行线程线程1
正在运行线程线程3
正在运行线程线程2
正在运行线程线程1
正在运行线程线程2
正在运行线程线程1
正在运行线程线程3


5.实现Runnable接口来创建线程.
    接口Runnable在包java.lang中.
    示例:
class MySuper {
 protected String myName;
 
 public MySuper(String Name) {
  this.myName = Name;
  System.out.println("初始化对象:" + this.myName);
 }
 
}

class MySub extends MySuper implements Runnable {

 public MySub(String Name) {
  super(Name);
 }
 
 //线程运行时执行的代码,实现接口Runnable
 public void run() {
  
  for (int i=0; i<3; i++) {
   System.out.println("运行线程" + super.myName);
   try {
    Thread.sleep(3);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  
 }
}

public class ThreadTest2 {
 
 public static void main(String[] args) {
  System.out.println("开始线程测试");
  
  MySub myobject1 = new MySub("对象1");
  MySub myobject2 = new MySub("对象2");
  
  Thread thread1 = new Thread(myobject1);
  Thread thread2 = new Thread(myobject2);
  thread1.start();
  thread2.start();
  
  System.out.println("结束线程测试");
 }
}
运行结果:
开始线程测试
初始化对象:对象1
初始化对象:对象2
结束线程测试
运行线程对象2
运行线程对象1
运行线程对象2
运行线程对象1
运行线程对象1
运行线程对象2


6.线程同步
    进程的多个线程共享一个对象,当一个线程在更新该对象时,另一个线程也试图更新或读取该对象,将会破坏数据的一致性。需要使用线程同步来避免共享对象的访问冲突。实质是对共享资源加锁。
    方法同步
    public synchronized void methodName([parameterList]){
        //操作共享对象
    }

    对象同步
    public void mymethod(){
        synchronized(this){
            //操作共享对象
        }
    }   

7.死锁
    死锁是指线程间互相等待对方的资源,而不能继续执行的情况。
    当线程同步synchronized使用不当可能导致死锁。持有一个共享资源的锁并试图获取另一个时,有可能发生死锁。
    造成死锁问题的本质是对共享资源的无序使用造成的,在程序设计时需要理清访问资源的顺序,应确保每个线程获取资源的顺序相同,释放资源与获取资源的顺序相反。

8.线程通信
    在多线程应用中,有时线程之间需要互相交流和等待,实现互相通信。可以通过共享的数据做到线程互相交流,通过线程控制方法使线程相互等待。
    java.lang.Object提供wait()/notify()/notifyAll()三个方法协调线程间的运行进度,实现线程通信。
    线程通信建立在生产者和消费者模型之上,一个线程产生输出(相当于生产产品,产生一串数据流,该线程为生产者),另一个线程进行输入(相当于消费者,消耗数据,该线程为消费者),先有生产者生产,才能有消费者消费,生产者没生产之前,通知消费者等待,生产后通知消费者消费,消费者消费后再通知生产者生产,即等待通知机制(Wait/Notify)。
    当线程获得某个对象的锁之后,若该行程调用wait()方法,则会退出所占用的处理器,并打开该对象的锁,转为阻塞状态,并允许其他同步语句获得对象锁。当执行条件满足后,将调用notify()方法,唤醒这个处于阻塞的线程,转为可运行状态,并有机会获得该对象的锁。但是,如果一个线程调用wait()方法后进入对该共享对象的等待状态,应确保有一个独立的线程最终会调用notify()方法,以使等待共享对象的线程回到可运行状态。
    线程通信示例
class ProducerThread extends Thread{
 long data = 0;
 
 ProducerThread() {
  start();
 }
 
 public void run() {
  synchronized(this) {
   System.out.println("开始生产");
   
   for(int i=0; i<100; i++) {
    data += i;
   }
   
   System.out.println("生产完毕");
   notify();
  }
 }
 
 synchronized public long getData() {
  try {
   wait();
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  
  return data;
 }
}

public class ThreadTest3 {
 
 public static void main(String[] args) {
  ProducerThread pt = new ProducerThread(); //
  System.out.println("生产结果: data=" + pt.getData());
 }
 
}
运行结果:
开始生产
生产完毕
生产结果: data=4950

9.线程组(Thread Group)
    在创建线程之前,可以创建一个ThreadGroup对象,然后将创建的线程依次加入.
    ThreadGroup tg = new ThreadGroup("myThreadGroup");
    Thread myThread1 = new Thread(tg, "writer");
    Thread myThread2 = new Thread(tg, "reader");
    myThread1.start();
    myThread2.start();
    线程组的方法
    getName()          返回线程组的名字
    getParent()        返回线程的父线程组的名字
    activeCount()      返回组中当前
    setMaxPriority(int pri)    设置线程组中线程的最高优先级别
    getMaxPriority()           返回线程组中线程的最高优先级别
    interrupt()                中断
    resume()                   唤醒
    stop()                     停止
    suspend()                  挂起
    setDaemon(boolean daemon)  将线程组设置为守护状态(常驻内存)
    isDaemon()                 判断是否为守护线程组
    isDestroyed()              判断线程组是否已被销毁
    parentOf(ThreadGroup g)    判断线程组是否是线程组g或g的子线程组
   
10.生产者消费者应用示例
// 共享数据
class ShareData {
 public int data;  //共享数据,可以扩展为复杂的数据
}

// 共享数据控制
class DataControl {
 private ShareData Data;
 private boolean writeable = true;
 
 public synchronized void setShareData(ShareData data) {
  if (!writeable) {
   try {
    wait();  // wait()方法需要放在一个同步段里,否则出现异常java.lang.IllegalMonitorStateException:
   } catch (InterruptedException e) {
    // e.printStackTrace();
   }
  }
  
  this.Data = data; 
  writeable = false;  //标记已经生产,设为只读,准备消费
  notify();           //线程通信,通知消费者已经生产,可以消费
 }
 
 public synchronized ShareData getShareData() {
  if (writeable) {
   try {
    wait();
   } catch (InterruptedException e) {
    //e.printStackTrace();
   }
  }
  
  writeable = true; //标记已经消费,设为可写,准备生产
  notify();         //线程通信,通知生产者需要生产
  
  return this.Data;
 }
 
}

// 生产者线程
class Producer extends Thread {
 private DataControl dc;
 
 Producer(DataControl dc) {
  this.dc = dc;
 }
 
 public void run() {
  for (int i=1; i<=10; i++) {
   try {
    Thread.sleep((int) Math.random() * 100);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   
   ShareData myData = new ShareData();
   myData.data = i;
   dc.setShareData(myData);
   System.out.println("生产者产生数据:" + myData.data);   
  }
 }
}

// 消费者线程
class Consumer extends Thread {
 private DataControl dc;
 
 Consumer(DataControl dc) {
  this.dc = dc;
 }
 
 public void run() {
  ShareData myData;
  
  do {
   try {
    Thread.sleep((int) Math.random() * 100);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   
   myData = dc.getShareData();
   System.out.println("消费者消费数据:" + myData.data);
   
  } while (myData.data <= 10);
 }
}

public class ThreadTest4 {

 public static void main(String[] args) {
  DataControl dc = new DataControl();
  new Consumer(dc).start();
  new Producer(dc).start();
 }
 
}
运行结果:
生产者产生数据:1
消费者消费数据:1
生产者产生数据:2
消费者消费数据:2
生产者产生数据:3
消费者消费数据:3
生产者产生数据:4
消费者消费数据:4
生产者产生数据:5
消费者消费数据:5
生产者产生数据:6
消费者消费数据:6
生产者产生数据:7
消费者消费数据:7
生产者产生数据:8
消费者消费数据:8
生产者产生数据:9
消费者消费数据:9
生产者产生数据:10
消费者消费数据:10

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

java学习笔记2(多线程)

  • 2011年08月30日 19:02
  • 210KB
  • 下载

UNIX多线程学习笔记

  • 2011年08月15日 13:46
  • 80KB
  • 下载

Java多线程(全)学习笔记(下)

资源下载地址:http://download.csdn.net/detail/cloudyxuq/3763101 七.Callable和Future接口     C#可以把任意方法包装成线程执行体...

多线程学习笔记与学习

  • 2011年07月04日 08:28
  • 85KB
  • 下载

Java学习笔记(二):枚举和多线程

1、枚举:          (1)For(Colorc:Color.values());    //获取Color枚举中所有对象;                             这个语句遍...

Java多线程设计模式详解学习笔记四——Immutable

public class Main { public static void main(String[] args) { Person alice = new Person("Alice", "...

Java学习笔记(十一)多线程

多线程: 进程与线程: 进程:同一个操作系统中执行的一个子程序,包含了三部分虚拟CPU、代码、数据 多进程:同一个操作系统中执行的多个并行的子程序。可以提高cpu的使用率 线程:在同一个进程当...

java个人学习笔记18(多线程之间通信+等待唤醒机制)

1.多线程之间的通信

java学习笔记之多线程生产者与消费者

生产者-消费者问题是一个经典的进程同步问题。在同一个进程地址空间内执行的两个线程生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产...

Java并发多线程学习笔记

标签(): java 多线程 并发编程 艺术原子操作的实现原理1、术语比较并交换 compare and swap(一个新值和旧值,比较旧值有没有发生变化,如果没有发生变化则交换成新值) CPU流水...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java多线程学习笔记
举报原因:
原因补充:

(最多只允许输入30个字)