分享

java线程基础

 obiwang 2011-03-24

java多线程

文章分类:Java编程
1. 创建线程的两种方式
2. 线程的生命周期
3. 同步的方式
4. 死锁
5. 生产消费模型、监控模型

创建线程的两种方式
Java代码 复制代码 收藏代码
  1. public class Thread1 extends Thread {   
  2.     private int j;   
  3.   
  4.     // 重写run方法   
  5.     public void run() {   
  6.         for (; j < 100; j++) {   
  7.             System.out.println(getName() + " " + j);   
  8.         }   
  9.     }   
  10.   
  11.     // 主函数   
  12.     public static void main(String args[]) {   
  13.         for (int i = 0; i < 100; i++) {   
  14.             // 打印主线程执行信息   
  15.             System.out.println(Thread.currentThread().getName() + " " + i);   
  16.             if (i == 20) {   
  17.                 // 新启两个线程   
  18.                 new Thread1().start();   
  19.                 new Thread1().start();   
  20.             }   
  21.         }   
  22.     }   
  23. }   
  24. public class Thread2 implements Runnable {   
  25.   
  26.     private int j;   
  27.   
  28.     // 实现run方法   
  29.     public void run() {   
  30.         for (; j < 100; j++) {   
  31.             System.out.println(Thread.currentThread().getName() + " " + j);   
  32.         }   
  33.     }   
  34.   
  35.     // 主方法   
  36.     public static void main(String args[]) {   
  37.            
  38.         for (int i = 0; i < 100; i++) {   
  39.             // 打印主线程执行信息   
  40.             System.out.println(Thread.currentThread().getName() + " " + i);   
  41.             if (i == 20) {   
  42.                 // 新启两个线程   
  43.                 Thread2 thread=new Thread2();   
  44.                 new Thread(thread,"新线程1").start();   
  45.                 new Thread(thread,"新线程2").start();   
  46.             }   
  47.         }   
  48.     }   
  49. }  

结果:



从图片上我们可以看到,第一张图片数据之间没有实现共享,但是第二张图片,我们可以看到线程1和线程2共享了线程类的实例属性,这是因为程序所创建的Runnable对象只是线程的的target,而多个线程可以共享一个target;
对于用继承Thread和实现Runnable,采用Runnable的话该实现类还可以进行继承,扩展性更强;
启动一个线程用的是start(),而不是run();如果直接用run()则会将它当作一个普通的方法来使用;用start(),则会将run方法当作线程执行体来处理;
前面的两个示例,实际上至少有三条线程,主线程和程序显示创建的两条线程;主线程的线程执行体不是由run方法来确定的,而是由main方法来确定的

线程的生命周期
当程序用new关键字创建一个线程之后,该线程就处于新建状态,此时它和其它Java对象一样,仅仅由Java虚拟机为其分配内存,并初始化了其成员变量的值。当线程调用了start方法后,该线程处于就绪状态;


同步的方式
一.synchronized关键字保证同步
    锁定方法:表示这个方法同时只能被一个线程访问
Java代码 复制代码 收藏代码
  1. //同步方法 同步监视器为this   
  2.     public synchronized int getM1(int count){   
  3.         return 1;   
  4.     }  

锁定对象:表示其限定的代码块只能同时被一个线程访问
Java代码 复制代码 收藏代码
  1. //同步代码块   
  2.     public void getM2(){   
  3.         synchronized(obj){   
  4.             //代码块,obj为同步监视器   
  5.         }   
  6.     }  

二.新用JDK1.5新的同步机制
Java代码 复制代码 收藏代码
  1. private Lock lock=new ReentrantLock();   
  2.     //在方法内使用同步锁   
  3.     public void getM3(){   
  4.         //开始锁   
  5.         lock.lock();   
  6.         //同步区。。。   
  7.         try{   
  8.                
  9.         }finally{   
  10.             //释放锁   
  11.             lock.unlock();   
  12.         }   
  13.            
  14.     }  

死锁
当两线程相互等待对方释放同步监视器时就会出现死锁,一旦出现死锁,整个程序既不会发生任何的异常,也不会给出任何的提示,只是所有线程处理阻塞状态,无法继续
Java代码 复制代码 收藏代码
  1. class A {   
  2.     synchronized void foo(B b) {   
  3.         String name = Thread.currentThread().getName();   
  4.   
  5.         System.out.println(name + " entered A.foo");   
  6.   
  7.         try {   
  8.             Thread.sleep(1000);   
  9.         } catch (Exception e) {   
  10.             System.out.println("A Interrupted");   
  11.         }   
  12.   
  13.         System.out.println(name + " trying to call B.last()");   
  14.         // 因为b对象被锁住了,调用b内的方法时,在等锁的释放   
  15.         b.last();   
  16.     }   
  17.   
  18.     synchronized void last() {   
  19.         System.out.println("Inside A.last");   
  20.     }   
  21. }   
  22.   
  23. class B {   
  24.     synchronized void bar(A a) {   
  25.         String name = Thread.currentThread().getName();   
  26.         System.out.println(name + " entered B.bar");   
  27.   
  28.         try {   
  29.             Thread.sleep(1000);   
  30.         } catch (Exception e) {   
  31.             System.out.println("B Interrupted");   
  32.         }   
  33.   
  34.         System.out.println(name + " trying to call A.last()");   
  35.         // 因为a对象被锁住了,调用a内的方法时,在等锁的释放   
  36.         a.last();   
  37.     }   
  38.   
  39.     synchronized void last() {   
  40.         System.out.println("Inside A.last");   
  41.     }   
  42. }   
  43.   
  44. class Deadlock implements Runnable {   
  45.     A a = new A();   
  46.   
  47.     B b = new B();   
  48.   
  49.     Deadlock() {   
  50.         Thread.currentThread().setName("MainThread");   
  51.         Thread t = new Thread(this"RacingThread");   
  52.         t.start();   
  53.   
  54.         a.foo(b); // 同步监视器为a   
  55.         System.out.println("Back in main thread");   
  56.     }   
  57.   
  58.     public void run() {   
  59.         b.bar(a); // 同步监视器为b   
  60.         System.out.println("Back in other thread");   
  61.     }   
  62.   
  63.     public static void main(String args[]) {   
  64.         new Deadlock();   
  65.     }   
  66. }  

生产消费模型、监控模型
Java代码 复制代码 收藏代码
  1. //生产消费模型   
  2. public class Main {   
  3.     public static void main(String args[]) {   
  4.         List<Egg> list = new ArrayList<Egg>();   
  5.         new Product(list).start();   
  6.         new Customer(list).start();   
  7.     }   
  8. }public class Egg {   
  9.     private int id;   
  10.     private String name;   
  11.   
  12.     public int getId() {   
  13.         return id;   
  14.     }   
  15.   
  16.     public void setId(int id) {   
  17.         this.id = id;   
  18.     }   
  19.   
  20.     public String getName() {   
  21.         return name;   
  22.     }   
  23.   
  24.     public void setName(String name) {   
  25.         this.name = name;   
  26.     }   
  27.   
  28.     public String toString() {   
  29.         return id + " " + name;   
  30.     }   
  31.   
  32. }public class Product extends Thread {   
  33.     private List<Egg> list;   
  34.     private int count;   
  35.   
  36.     public Product(List<Egg> list) {   
  37.         this.list = list;   
  38.     }   
  39.   
  40.     // 重写run方法   
  41.     public void run() {   
  42.         System.out.println("生产线程启动");   
  43.         while (true) {   
  44.             try {   
  45.                 Thread.sleep(100);   
  46.                 synchronized (list) {   
  47.                     //还有鸡蛋时   
  48.                     while (list.size() > 0) {   
  49.                           list.wait();   
  50.                     }   
  51.                     //没有鸡蛋时   
  52.                     while(list.size()==0){   
  53.                         Egg egg=new Egg();   
  54.                         egg.setId(count++);   
  55.                         egg.setName("鸡蛋");   
  56.                         System.out.println("生产线程生产"+egg.toString());   
  57.                         list.add(egg);   
  58.                         //通知消费线程   
  59.                         list.notify();   
  60.                     }   
  61.                 }   
  62.             } catch (InterruptedException e) {   
  63.                 e.printStackTrace();   
  64.             }   
  65.         }   
  66.     }   
  67. }public class Customer extends Thread {   
  68.     private List<Egg> list;   
  69.   
  70.     public Customer(List<Egg> list) {   
  71.         this.list = list;   
  72.     }   
  73.     // 重写run方法   
  74.     public void run() {   
  75.         System.out.println("消费线程启动");   
  76.         while (true) {   
  77.             try {   
  78.                 Thread.sleep(100);   
  79.                 synchronized (list) {   
  80.                     //没有则等待   
  81.                     while (list.size() == 0) {   
  82.                          list.wait();    
  83.                     }   
  84.                     //有鸡蛋时   
  85.                     while(list.size()>0){   
  86.                            
  87.                         System.out.println("消费线程消费"+list.remove(0).toString());   
  88.                         //通知生产线程   
  89.                         list.notify();   
  90.                     }   
  91.                 }   
  92.             } catch (InterruptedException e) {   
  93.                 e.printStackTrace();   
  94.             }   
  95.         }   
  96.   
  97.     }   
  98. }  

Java代码 复制代码 收藏代码
  1. //监控模型public class Control implements Runnable {   
  2.     // 存放统计线程的队列   
  3.     private static List<CountFile> list = new ArrayList<CountFile>();   
  4.   
  5.     // 主函数   
  6.     public static void main(String args[]) {   
  7.         // 取得系统的根目录个数   
  8.         java.io.File[] dirF = java.io.File.listRoots();   
  9.         // 根据目录创建统计纯种个数   
  10.         for (int i = 0; i < dirF.length; i++) {   
  11.             CountFile cf = new CountFile(dirF[i].getAbsolutePath());   
  12.             cf.start();   
  13.             list.add(cf);   
  14.         }   
  15.         System.out.println(dirF.length + " 个统计线程已启动");   
  16.         // 启动监视线程   
  17.         new Thread(new Control()).start();   
  18.         System.out.println("监视线程已启动");   
  19.     }   
  20.   
  21.     // 实现run方法   
  22.     public void run() {   
  23.         boolean flag = true;   
  24.         String result = "";   
  25.         while (flag) {   
  26.             for (int i = 0; i < list.size(); i++) {   
  27.                 if (list.get(i).isFinished()) {   
  28.                     // 取得统计结果   
  29.                     result += list.get(i).getResult();   
  30.                     // 移出统计完的线程   
  31.                     list.remove(i);   
  32.                 }   
  33.             }   
  34.             // 全部统计完   
  35.             if (list.isEmpty()) {   
  36.                 flag = false;   
  37.             }   
  38.             try {   
  39.                 Thread.sleep(1000);   
  40.             } catch (Exception e) {   
  41.                 e.printStackTrace();   
  42.             }   
  43.         }   
  44.         System.out.println("统计结果如下:");   
  45.         System.out.println(result);   
  46.     }   
  47. }public class CountFile extends Thread {   
  48.     private String root;// 进行搜索的根目录的名字   
  49.     private int lengthCount;// 所有文件长度   
  50.     private int dirCount;// 目录数   
  51.     private int realFileCount;// 统计的真正文件数量   
  52.     private boolean finished = false;   
  53.   
  54.     // 构造时传入搜索根目录名   
  55.     public CountFile(String root) {   
  56.         this.root = root;   
  57.     }   
  58.   
  59.     /**  
  60.      * 查看线程是否统计结束  
  61.      *   
  62.      * @return  
  63.      */  
  64.     public boolean isFinished() {   
  65.         return finished;   
  66.     }   
  67.   
  68.     /**  
  69.      * 返回统计结果  
  70.      *   
  71.      * @return  
  72.      */  
  73.     public String getResult() {   
  74.         StringBuffer result = new StringBuffer();   
  75.         result.append(root + "盘统计结果如下:\r\n");   
  76.         result.append("  文件数量: " + realFileCount);   
  77.         result.append("   目录数: " + dirCount);   
  78.         result.append("   文件总长度(单位K): " + lengthCount / 1204);   
  79.         result.append("\r\n");   
  80.         return result.toString();   
  81.     }   
  82.   
  83.     // 重写run方法   
  84.     public void run() {   
  85.         long start = System.currentTimeMillis();   
  86.         lengthCount = countProcess(root);   
  87.         long cost = System.currentTimeMillis() - start;   
  88.         finished = true;   
  89.     }   
  90.   
  91.     /**  
  92.      * 统计目录下文件的长度  
  93.      *   
  94.      * @param root  
  95.      *            要统计的目录  
  96.      * @return 目录下文件的长度  
  97.      */  
  98.     private int countProcess(String root) {   
  99.         int count = 0;   
  100.         File dirFile = new File(root);   
  101.         // 目录不存在   
  102.         if (!dirFile.exists()) {   
  103.             return count;   
  104.         }   
  105.         // 获得目录下的所有文件组成的数组   
  106.         File[] subFile = dirFile.listFiles();   
  107.         if (subFile == null) {   
  108.             return count;   
  109.         }   
  110.         // 对这个数组进行遍历   
  111.         for (int i = 0; i < subFile.length; i++) {   
  112.             // 是个目录   
  113.             if (subFile[i].isDirectory()) {   
  114.                 dirCount++;   
  115.                 count += countProcess(subFile[i].getAbsolutePath());// 用递归计算该目录下的文件长度   
  116.             }   
  117.             // 是一个文件   
  118.             if (subFile[i].isFile()) {   
  119.                 realFileCount++;   
  120.                 count += subFile[i].length();   
  121.             }   
  122.         }   
  123.         return count;   
  124.     }   
  125. }  
  • 大小: 4.9 KB
  • 大小: 5.7 KB
  • 大小: 37.9 KB

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多