??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲综合色视频在线观看,中文字幕在线亚洲精品,亚洲AV无码国产精品色http://www.tkk7.com/junglesong/category/29589.html世上本无难事Q心以ؓ难,斯乃真难。苟不存一难之见于心,则运用之术自出?/description>zh-cnMon, 25 Feb 2008 22:46:55 GMTMon, 25 Feb 2008 22:46:55 GMT60工序d的线E模?/title><link>http://www.tkk7.com/junglesong/archive/2008/02/25/182095.html</link><dc:creator>junglesong的博?/dc:creator><author>junglesong的博?/author><pubDate>Mon, 25 Feb 2008 14:40:00 GMT</pubDate><guid>http://www.tkk7.com/junglesong/archive/2008/02/25/182095.html</guid><wfw:comment>http://www.tkk7.com/junglesong/comments/182095.html</wfw:comment><comments>http://www.tkk7.com/junglesong/archive/2008/02/25/182095.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/junglesong/comments/commentRss/182095.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/junglesong/services/trackbacks/182095.html</trackback:ping><description><![CDATA[     摘要: 工序d指流水线式的工作场景Q下一l工人的工g是上一l工人的成品Q一个活做完自己的部分就往下传Q直到活完成为止? Z~程方便化了各个工序的工Ӟ把它们都当成一L(fng)了? 代码Q?package com.sitinspring.autotask.domain; import com.sitinspring.autotask.util.IdUtil; ...  <a href='http://www.tkk7.com/junglesong/archive/2008/02/25/182095.html'>阅读全文</a><img src ="http://www.tkk7.com/junglesong/aggbug/182095.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/junglesong/" target="_blank">junglesong的博?/a> 2008-02-25 22:40 <a href="http://www.tkk7.com/junglesong/archive/2008/02/25/182095.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>d锁的使用http://www.tkk7.com/junglesong/archive/2008/02/22/181400.htmljunglesong的博?/dc:creator>junglesong的博?/author>Fri, 22 Feb 2008 06:28:00 GMThttp://www.tkk7.com/junglesong/archive/2008/02/22/181400.htmlhttp://www.tkk7.com/junglesong/comments/181400.htmlhttp://www.tkk7.com/junglesong/archive/2008/02/22/181400.html#Feedback0http://www.tkk7.com/junglesong/comments/commentRss/181400.htmlhttp://www.tkk7.com/junglesong/services/trackbacks/181400.html本文内容

何时该用读写锁.
d锁的写法.
理解d锁和U程互斥的区别?/p>

复习(fn)-同步化的概念

当一个方法或代码块被声明成synchronizedQ要执行此代码必d取得一个对象实例或this的锁定,q个锁定要在synchronized修饰的方法或代码块执行完后才能释放掉Q无D代码是怎样q回的,是正常运行还是异常运行)。每个对象只有一个锁定,如果有两个不同的U程试图同时调用同一对象的同步方法,最l只会有一个能q行此方法,另外一个要{待W一个线E释放掉锁定后才能运行此Ҏ(gu)?/p>

d锁应用的场合

我们有时会遇到对同一个内存区域如数组或者链表进行多U程d的情?一般来说有以下几种处理方式: 1.不加M限制,多见于读取写入都很快的情?但有时也会出现问? 2.对读写函数都加以同步互斥,q下问题是没?但效率也下去?比如说两个读取线E不是非要排队进入不? 3.使用d?安全和效率都得到了解?特别合适读U程多于写线E的情况.也就是下面将要展现的模式.

d锁的意图

d锁的本意是分别对d状态进行互斥区?有互斥时才加?否则放行.互斥的情冉|: 1.d互斥. 2.写写互斥. 不互斥的情况?读读,q种情况不该加以限制. E序是要让锁对象知道当前读写状?再根据情况对d的线E进行锁定和解锁?/p>

dU程都要操作的数据类

dU程都要操作的数据是链表datas?br /> 注意其中try...finally 的写?它保证了加锁解锁q程是成对调用的

 

lpublic class DataLib {
     private List<String> datas;
 
     private ReadWriteLock lock;
 
     public DataLib() {
         datas = new ArrayList<String>();
         lock = new ReadWriteLock();
     }
 
     // 写入数据,q时不能d
     public void writeData(List<String> newDatas) {
         try {
             lock.writeLock();
             Test.sleep(2);
             datas=newDatas;
         } finally {
             lock.writeUnlock();
         }
     }
 
     // d数据,q时不能写入
     public List<String> readData() {
         try {
             lock.readLock();
             Test.sleep(1);            
             return datas;
         } finally {
             lock.readUnlock();
         }
 
     }
 
 }



 

d锁ReadWriteLockc?

public class ReadWriteLock{
    // ȝ?br />     private boolean isRead;
   
    // 写状?br />     private boolean isWrite;
   
    public synchronized void readLock(){
        // 有写入时dU程停止
        while(isWrite){
            try{   
                System.out.println("有线E在q行写入,dU程停止,q入{待状?);
                wait();
            }
            catch(InterruptedException ex){
                ex.printStackTrace();
            }
        }
       
        System.out.println("讑֮锁ؓd状?);
        isRead=true;
    }
   
    public synchronized void readUnlock(){
        System.out.println("解除d?);
        isRead=false;
        notifyAll();
    }

     public synchronized void writeLock(){
        // 有读取时dU程停止
        while(isRead){
            try{   
                System.out.println("有线E在q行d,写入U程停止,q入{待状?);
                wait();
            }
            catch(InterruptedException ex){
                ex.printStackTrace();
            }
        }
       
        // 有写入时写入U程也一栯停止
        while(isWrite){
            try{   
                System.out.println("有线E在q行写入,写入U程停止,q入{待状?);
                wait();
            }
            catch(InterruptedException ex){
                ex.printStackTrace();
            }
        }
       
        System.out.println("讑֮锁ؓ写入状?);
        isWrite=true;
    }
   
    public synchronized void writeUnlock(){
        System.out.println("解除写入?);
        isWrite=false;
        notifyAll();
    }
}

写线E类Writer -它用于往DataLibcd例中的datas字段写数?/p>

分析其中dataLib字段的用意?br /> 注意q记住其中持l调用及使用随机数的Ҏ(gu)?/p>

 

lpublic class Writer implements Runnable{
     private DataLib dataLib;
     private static final Random random=new Random();
     private String[] mockDatas={"?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>"};    
     
     public Writer(DataLib dataLib,String[] mockDatas){
         this.dataLib=dataLib;
         this.mockDatas=mockDatas;
         
         Thread thread=new Thread(this);
         thread.start();
     }
     
     public void run(){
         while(true){
             Test.sleep(random.nextInt(3));
             
             int startIndex=random.nextInt(mockDatas.length);
             
             ArrayList<String> newDatas=new ArrayList<String>();
             for(int i=startIndex;i<mockDatas.length;i++){
                 newDatas.add(mockDatas[i]);
             }
             
             dataLib.writeData(newDatas);
         }
     }
 }

ȝE类Reader  -它用于从DataLibcd例中的datas字段d数据

分析其中dataLib字段的用意?br /> 注意q记住其中持l调用及使用随机数的Ҏ(gu)?/p>

public class Reader implements Runnable{
    private DataLib dataLib;
    private static final Random random=new Random();
   
    public Reader(DataLib dataLib){
        this.dataLib=dataLib;
   
        Thread thread=new Thread(this);
        thread.start();
    }
   
    public void run(){
        while(true){
            Test.sleep(random.nextInt(2));           
            List<String> datas=dataLib.readData();
           
            System.out.print(">>取得数组?");
            for(String data:datas){
                System.out.print(data+",");
            }
            System.out.print("\n");
        }
    }
}

代码运行v?/p>

双的代码创Z两个写线E和三个ȝE,它们都是对dataLib实例q行操作的?br /> 五个U程都有一个dataLib字段Q都提供了一个带参构造函Cldatas字段赋|q就保证了五个线E操作的都是一个实例的同一字段Q也是同一片内存?br /> d锁就是对q五个线E进行控制的?br /> 当有一个读U程在操作时Q其它的写线E无法进行操作,ȝE可以正常操作,互不q扰?br /> 当有一个写U程在操作时Q其它的ȝE无法进行操作?/p>

 

 public class Test{
     public static void main(String[] args){
         DataLib dataLib=new DataLib();
         
         String[] mockDatas1={"?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>"};
         Writer writer1=new Writer(dataLib,mockDatas1);
         
         String[] mockDatas2={"?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>","?/span>"};
         Writer writer2=new Writer(dataLib,mockDatas2);
         
         Reader reader1=new Reader(dataLib);
         Reader reader2=new Reader(dataLib);
         Reader reader3=new Reader(dataLib);
     }
     
     
     // 用于延时
     public static void sleep(int sleepSecond){
         try{
             Thread.sleep(sleepSecond*1000);
         }
         catch(Exception ex){
             ex.printStackTrace();
         }
     }
 }

当多个线E试囑֯同一内容q行d操作旉合使用d锁?br /> L(fng)解ƈCReadWriteLockc读写锁的写?
d锁相对于U程互斥的优势在于高效,它不会对两个ȝE进行盲目的互斥处理Q当ȝE数量多于写U程其如此Q当全是写线E时两者等效?/p>

]]>
U程锁的使用http://www.tkk7.com/junglesong/archive/2008/02/22/181395.htmljunglesong的博?/dc:creator>junglesong的博?/author>Fri, 22 Feb 2008 06:20:00 GMThttp://www.tkk7.com/junglesong/archive/2008/02/22/181395.htmlhttp://www.tkk7.com/junglesong/comments/181395.htmlhttp://www.tkk7.com/junglesong/archive/2008/02/22/181395.html#Feedback0http://www.tkk7.com/junglesong/comments/commentRss/181395.htmlhttp://www.tkk7.com/junglesong/services/trackbacks/181395.html本文内容

何时该用线E锁.
U程锁的写法.
以线E锁的例子来理解U程的调度?/p>

使用U程锁的场合

E序中经帔R用多U程处理Q这可以充分利用pȝ资源Q羃短程序响应时_改善用户体验Q如果程序中只用单U程Q那么程序的速度和响应无疑会大打折扣?br /> 但是Q程序采用了多线E后Q你必认真考虑U程调度的问题,如果调度不当Q要么造成E序出错Q要么造成荒谬的结果?/p>

一个讽刺僵化体制的W话

前苏联某官员去视察植?wi)造林的情况,现场他看C个h在远处挖坑,其后不远另一个h在把刚挖出的坑逐个填上Q官员很费解于是询问陪同人员Q当地管理h员说“负责U树(wi)的h今天病了”?br /> 上面q个W话如果发生在程序中是U程调度的问题,U树(wi)q个d有三个线E:挖坑U程Q种?wi)线E和填坑U程Q后面的U程必须{前一个线E完成才能进行,而不是按旉序来进行,否则一旦一个线E出错就会出C面荒谬的l果?/p>

用线E锁来处理两个线E先后执行的情况

在程序中Q和U树(wi)一P很多d也必M定的先后秩序执行,对于两个U程必须以先后秩序执行的情况Q我们可以用U程锁来处理?br /> U程锁的大致思想是:如果U程A和线EB会执行实例的两个函数a和bQ如果A必须在B之前q行Q那么可以在Bq入b函数时让Bq入wait setQ直到A执行完a函数再把B从wait set中激zR这样就保证了B必定在A之后q行Q无论在之前它们的时间先后顺序是怎样的?/p>

U程锁的代码

如右QSwingComponentLock的实例就是一个线E锁Qlock函数用于锁定U程Q当完成状态isCompleted为false时进入的U程会进入SwingComponentLock的实例的wait setQ已完成则不会;要激zSwingComponentLock的实例的wait set中等待的U程需要执行unlock函数?/p>

public class SwingComponentLock {
  // 是否初始化完?br />   boolean isCompleted = false;

  /**
   * 锁定U程
   */
  public synchronized void lock() {
    while (!isCompleted) {
      try {
        wait();
      } catch (Exception e) {
        e.printStackTrace();
        logger.error(e.getMessage());
      }
    }
  }

  /**
   * 解锁U程
   *
   */
  public synchronized void unlock() {
    isCompleted = true;
    notifyAll();
  }
}

U程锁的使用

public class TreeViewPanel extends BasePanel {
  // 表空间和表树(wi)
  private JTree tree;

  // q个是防?wi)还未初始化好就被刷新用?br />   private SwingComponentLock treeLock;

  protected void setupComponents() {
    // 初始化锁
    treeLock = new SwingComponentLock();

    // 创徏根节?br />     DefaultMutableTreeNode root = new DefaultMutableTreeNode("DB");
    tree = new JTree(root);

    // 讄布局q装入树(wi)
    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
    add(new JScrollPane(tree));

    // 讄?wi)节点的图?br />     setupTreeNodeIcons();

    // 解除Ҏ(gu)(wi)的锁?br />     treeLock.unlock();
  }

 /**
   * h?wi)视?br />    *
   * @param schemas
   */
  public synchronized void refreshTree(List<SchemaTable> schemas) {
    treeLock.lock();

    DefaultTreeModel model = (DefaultTreeModel) tree.getModel();

    DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
    root.removeAllChildren();

    for (SchemaTable schemaTable : schemas) {
      DefaultMutableTreeNode schemaNode = new DefaultMutableTreeNode(
          schemaTable.getSchema());

      for (String table : schemaTable.getTables()) {
        schemaNode.add(new DefaultMutableTreeNode(table));
      }

      root.add(schemaNode);
    }

    model.reload();
  }

讲解

上页中,setupComponents函数是SwingȝE执行的Q而refreshTree函数是另外的U程执行Q初始化时程序开辟一个线E执行,其后执行qh作决定)?refreshTree函数必须要等setupComponents函数把tree初始化完毕后才能执行Q而tree初始化的旉较长Q可能在初始化的q程中执行refreshTree的线E就q入了,q就会造成问题?br /> E序使用了一个SwingComponentLock来解册个问题,setupComponents一开始就创徏SwingComponentLock的实例treeLockQ然后执行refreshTree的线E以来就会进入treeLock的wait setQ变成等待状态,不会往下执行,q是不管tree是否初始化完毕都不会出错Q而setupComponents执行到底部会ȀztreeLock的wait set中等待的U程Q这时再执行refreshTree剩下的代码就不会有Q何问题,因ؓsetupComponents执行完毕tree已经初始化好了?br /> 让线E等待和ȀzȝE的代码都在SwingComponentLockcMQ这L(fng)装对复用很有好处,如果其它复杂lg如table也要依此办理直接创徏SwingComponentLockcȝ实例可以了。如果把wait和notifyAll写在TreeViewPanelcM׃会这h便了?/p>

ȝ

U程锁用于必M固定序执行的多个线E的调度?br /> U程锁的思想是先锁定后序U程Q然后让U序U程完成d再接触对后序U程的锁定?br /> U程锁的写法和用一定要理解记忆下来?/p>

 



]]>
U程调度实例http://www.tkk7.com/junglesong/archive/2008/02/22/181394.htmljunglesong的博?/dc:creator>junglesong的博?/author>Fri, 22 Feb 2008 06:17:00 GMThttp://www.tkk7.com/junglesong/archive/2008/02/22/181394.htmlhttp://www.tkk7.com/junglesong/comments/181394.htmlhttp://www.tkk7.com/junglesong/archive/2008/02/22/181394.html#Feedback0http://www.tkk7.com/junglesong/comments/commentRss/181394.htmlhttp://www.tkk7.com/junglesong/services/trackbacks/181394.html本文内容

本文从一个现实例子来实际说明U程调度Ҏ(gu)waitQnotify和notifyAll的用?/p>

工厂中Q务的领受和执?/strong>

某工厂执行这L(fng)机制Q当生d下达到R间时会统一攑֜一个地方,由工Z来取zR?br /> 工h取活如此执行Q一个工人手头只能有一个活Q如果没做完不能做下一个,如果做完了则可以到公q地方d一个;如果没有zd取则闲着直到来活为止?/p>

本文是讲述怎样使用U程的调度三Ҏ(gu)waitQnotify和notifyAll来实现这一现实zd的?/p>

dcTask-它用来实C?#8221;z?#8221;,其中关键的成员是完成需消耗的工时数manHour和已l完成的工时数completed

public class Task implements Comparable {
  private String id;

  private String name;

  // 完成需消耗的工时?br />   private int manHour;

  // 已经完成的工时数
  private int completed;

  // 优先U?br />   private int priority;

  // 接受d?br />   private Worker worker;

  public Task(String name, int manHour) {
    this(name, manHour, 0);
  }

  public Task(String name, int manHour, int priority) {
    id = IdUtil.generateId();
    this.name = name;
    this.manHour = manHour;
    this.priority = priority;
    this.completed = 0;
  }
 // d是否完成
  public boolean isCompleted() {
    return completed >= manHour;
  }

  // d完成?br />   public void addCompleted(int n) {
    completed += n;

    if (isCompleted()) {
      completed = manHour;

      if (worker != null) {
        System.out.println("d"+this+"处理完毕!");
      }
    }
  }

  public int compareTo(Object obj) {
    Task another = (Task) obj;
    return (another.priority) - this.priority;
  }

  public String toString() {
    return "d?" + name + " 工h?" + worker.getName() + " 完成?" + completed
        * 100 / manHour + "%";
  }
 
  public String getCompletedRatio() {
    return " 完成?" + completed * 100 / manHour + "%";
  }
...getter/setterҎ(gu)省略..

}

d库类TaskLibrary

q个cd应现实中的取zȝ地方,每个zTask攑֜q个cȝ成员tasks?有两个方法来d单个d和多个Q?q有一个fetchTaskҎ(gu)来供工h领受d.

public class TaskLibrary {
  private List<Task> tasks;

  public TaskLibrary() {
    tasks = new LinkedList<Task>();
  }

  // d单个d
  public synchronized void addTask(Task task) {
    tasks.add(task);
    notifyAll();
  }

  // d多个d
  public synchronized void addTasks(List<Task> moreTasks) {
    tasks.addAll(moreTasks);
    notifyAll();
  }

  public int getTaskSize() {
    return tasks.size();
  }

  // 工h领受d
  public synchronized Task fetchTask(Worker worker) {
    while (tasks.size() == 0) {
      try {
        System.out.println("d告罄");
        System.out.println("工h:" + worker.getName() + "q入闲置状?);
        wait();
      } catch (InterruptedException ex1) {
        ex1.printStackTrace();
      }
    }

    Task task = tasks.get(0);
    System.out.println("工h:" + worker.getName() + "取得d:" + task.getName());
    tasks.remove(task);
    return task;
  }
}

工hcWorker

public class Worker implements Runnable {
  private String id;

  private String name;

  private Task currTask;

  private TaskLibrary taskLibrary;

  // 工作速度
  private int speed;

  public Worker(String name, int speed, TaskLibrary taskLibrary) {
    id = IdUtil.generateId();
    this.currTask = null;
    this.name = name;
    this.speed = speed;
    this.taskLibrary = taskLibrary;

    doWork();
  }

  // 开始干z?br />   public void doWork() {
    Thread thread = new Thread(this);
    thread.start();
  }
 // 真正q活
  public void run() {
    while (true) {
      if (currTask == null || currTask.isCompleted()) {
        currTask = taskLibrary.fetchTask(this);
        currTask.setWorker(this);
      }

      try {
        Thread.sleep(1000);
        System.out.println("正在处理的Q? + currTask + " 完成?
            + currTask.getCompletedRatio() + "?");
        currTask.addCompleted(speed);
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    }
  }
。。?br /> }

q行代码

  TaskLibrary taskLibrary=new TaskLibrary();  
  
  taskLibrary.addTask(new Task("培训",8));
  
  List<Task> moreTasks=new LinkedList<Task>();
  moreTasks.add(new Task("锻?,4));
  moreTasks.add(new Task("打磨",5));
  moreTasks.add(new Task("车阶?,6));
  moreTasks.add(new Task("热处?,7));
  moreTasks.add(new Task("ȝ",8));
  moreTasks.add(new Task("镗孔",60));
  moreTasks.add(new Task("d",10));
  moreTasks.add(new Task("拉槽",11));
  
  taskLibrary.addTasks(moreTasks); 
  
  Worker worker01=new Worker("王进?,1,taskLibrary);
  Worker worker02=new Worker("时传?,2,taskLibrary);
  Worker worker03=new Worker("张秉?,3,taskLibrary);
  Worker worker04=new Worker("徐虎",3,taskLibrary);
  
  taskLibrary.addTask(new Task("铔R?,8));
  sleep(1);
  taskLibrary.addTask(new Task("校验",9));
  sleep(2);
  taskLibrary.addTask(new Task("内务",10));
  sleep(3);

q行情况分析

一开始先初始化Q务库,然后q行lQ务库中添加Q?初始化工人实例时会把d库实例的地址传入,工h实例初始化完毕后会调用doWork函数MQ务库取Q务开始做,q会q入TaskLibrarycȝfetchTask函数,q时如果没有则会让工人等?有则把第一个Q务给?然后周而复始进行这一q程.

q行l果CZ

 工h:王进喜取得Q?培训 工h:时传详取得Q?锻?工h:张秉贵取得Q?打磨 工h:徐虎取得d:车阶?正在处理的Q务Q务名:培训 工h?王进?nbsp;完成?0% 完成?nbsp;完成?0%? 正在处理的Q务Q务名:锻?nbsp;工h?时传?nbsp;完成?0% 完成?nbsp;完成?0%? 正在处理的Q务Q务名:打磨 工h?张秉?nbsp;完成?0% 完成?nbsp;完成?0%? 正在处理的Q务Q务名:车阶?nbsp;工h?徐虎 完成?0% 完成?nbsp;完成?0%? 正在处理的Q务Q务名:培训 工h?王进?nbsp;完成?12% 完成?nbsp;完成?12%? 正在处理的Q务Q务名:锻?nbsp;工h?时传?nbsp;完成?50% 完成?nbsp;完成?50%? dd?锻?nbsp;工h?时传?nbsp;完成?100%处理完毕! 工h:时传详取得Q?热处?正在处理的Q务Q务名:打磨 工h?张秉?nbsp;完成?60% 完成?nbsp;完成?60%? dd?打磨 工h?张秉?nbsp;完成?100%处理完毕! 正在处理的Q务Q务名:车阶?nbsp;工h?徐虎 完成?50% 完成?nbsp;完成?50%? dd?车阶?nbsp;工h?徐虎 完成?100%处理完毕! 工h:徐虎取得d:ȝ 工h:张秉贵取得Q?镗孔 正在处理的Q务Q务名:培训 工h?王进?nbsp;完成?25% 完成?nbsp;完成?25%? 正在处理的Q务Q务名:热处?nbsp;工h?时传?nbsp;完成?0% 完成?nbsp;完成?0%? 正在处理的Q务Q务名:ȝ 工h?徐虎 完成?0% 完成?nbsp;完成?0%? 正在处理的Q务Q务名:镗孔 工h?张秉?nbsp;完成?0% 完成?nbsp;完成?0%? 正在处理的Q务Q务名:培训 工h?王进?nbsp;完成?37% 完成?nbsp;完成?37%? 正在处理的Q务Q务名:热处?nbsp;工h?时传?nbsp;完成?28% 完成?nbsp;完成?28%? 正在处理的Q务Q务名:ȝ 工h?徐虎 完成?37% 完成?nbsp;完成?37%? 正在处理的Q务Q务名:镗孔 工h?张秉?nbsp;完成?5% 完成?nbsp;完成?5%? 正在处理的Q务Q务名:培训 工h?王进?nbsp;完成?50% 完成?nbsp;完成?50%? 正在处理的Q务Q务名:热处?nbsp;工h?时传?nbsp;完成?57% 完成?nbsp;完成?57%? 正在处理的Q务Q务名:ȝ 工h?徐虎 完成?75% 完成?nbsp;完成?75%? dd?ȝ 工h?徐虎 完成?100%处理完毕! 工h:徐虎取得d:d

 



]]>
U程的协?/title><link>http://www.tkk7.com/junglesong/archive/2008/02/22/181390.html</link><dc:creator>junglesong的博?/dc:creator><author>junglesong的博?/author><pubDate>Fri, 22 Feb 2008 06:13:00 GMT</pubDate><guid>http://www.tkk7.com/junglesong/archive/2008/02/22/181390.html</guid><wfw:comment>http://www.tkk7.com/junglesong/comments/181390.html</wfw:comment><comments>http://www.tkk7.com/junglesong/archive/2008/02/22/181390.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/junglesong/comments/commentRss/181390.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/junglesong/services/trackbacks/181390.html</trackback:ping><description><![CDATA[<p><strong>本文内容</strong></p> <p>Javaq行U程调度的方?<br /> 如何让线E进入等?<br /> wait set概念的理?<br /> 如何Ȁzȝ待状态的U程.</p> <p><strong>q行U程协调的方?/strong></p> <p>从上一章《线E的互斥》中我们知道Q当Ҏ(gu)体或代码块被synchronizedҎ(gu)修饰Ӟ有一个线E在执行q部分代码时Q其它线E无法同时执行这部分代码。但如果我们惌行更高效的处理如d调整U程而不是让U程被动{待和盲目竞争时该怎么处理呢?<br /> 在Java中,有三个方法可以对U程q行d高效的控Ӟ它们是waitQnotify和notifyAll?br /> wait是主动让U程{待的方法,而notify和notifyAll则是Ȁzȝ待中的线E的Ҏ(gu)。他们都是ObjectcȝҎ(gu)Q也是说Q何对象都可以使用q三个方法?/p> <p><strong>Wait Set-U程的休息室</strong></p> <p>在学?fn)用waitQnotify和notifyAllq三个方法之前,我们可以先理解一下Wait Set的概念,它是一个在某实例执行waitҎ(gu)Ӟ停止操作的线E的集合Q类gU程的休息室Q每个实例都拥有q样一个休息室?br /> WaitҎ(gu)是用来把U程请入q个休息室的Q而notify和notifyAllq两个方法是用来进入休息室休息的线E激zȝ?br /> wait Set是一个虚拟的概念Q它既不是实例的字段,也不是可以获取在实例上wait中线E的列表的方?它只是用来帮助我们理解线E的{待和激zȝ?/p> <p><strong>WaitҎ(gu)Q将U程攑օWait Set</strong></p> <p>使用WaitҎ(gu)ӞU程卌入Wait set。如U程在执行代码时遇到q样的语句:xxObj.wait();则目前的U程会暂时停止运?q入实例xxObj的wait Set.<br /> 当线E进入Wait Set?即释放了对该实例的锁?也就是说,即是被synchronized修饰的方法和代码?当第一个线E进入实例的wait Set{待?其它U程可以再q入q部分代码了.<br /> wait()前如果不写某对象表示其前面的对象是this, wait()=this.wait();</p> <p><strong>notifyҎ(gu)-从wait set中激zM个线E?/strong></p> <p>使用notifyҎ(gu)?E序会从处于{待的实例的休息室中ȀzM个线E?代码如下:<br /> xxObj.notify();E序从xxObj的wait set中挑Z个激z?q个U程卛_备退出wait set.当当前线E释攑֯xxObj的锁定后Q这个线E即获取q个锁定Q从上次的停止点-执行wait的地方开始运行?br /> U程必须有调用的实例的锁?才能执行notifyҎ(gu).<br /> Wait set中处于等待状态的U程有多?具体Ȁz那一个依环境和系l而变,事先无法辩明.我们大致可理解ؓ随机挑选了一?</p> <p><strong>notifyAllҎ(gu)-Ȁzwait set中所有等待的U程</strong></p> <p>当执行notifyAllҎ(gu)?实例中所有处于等待状态的U程都会被激z?代码?<br /> xxObj.notifyAll();执行此代码后xxObj的wait set中所有处于等待中的线E都会被Ȁz?但具体那个线E获取执行waitҎ(gu)旉攄锁定要靠竞争,最l只能有一个线E获得锁?其它的线E只能l回ȝ?<br /> notifyAll与notify的差异在于notifyAllȀzL有wait set中等待的U程,而notify只激zd中的一?</p> <p><strong>该用notifyq是notifyAll</strong></p> <p>:<br /> 1) 选择notifyAll比notifyE_安全,如果notify处理得不?E序会有隐?zhn)?<br /> 2) 选择notifyAll比notify可靠,是大多数E序的首?<br /> 3) 当你对代码已l很清楚,对线E理解也很透彻?你可以选择使用notify,发挥其处理速度高的优势.</p> <p><strong>当前U程必须持有Ʋ调用实例的锁定,才能调用wait,notify和notifyAllq三个方?</strong></p> <p>如果代码是xxObj.notifyAll(或wait, notify)(),则这行代码必d于synchronized(xxObj){…}代码块中.<br /> 如果代码是this.notifyAll(或wait, notify)(),则这行代码必d于synchronized修饰的方法中.<br /> 前面说过, notifyAll和notify会激zȝE去获得q入wait旉攄锁定,但这个锁定要{刚才执行notifyAll或notifyҎ(gu)的线E释放这个锁定才能获?</p> <p><strong>ȝ</strong></p> <p>1) wait,notify和notifyAll都是java.lang.Object的方?它们用来对线E进行调?<br /> 2) obj.wait()是把执行q句的线E放入obj的wait set?<br /> 3) obj.notify()是从wait set中唤醒一个线E?q个U程在当前线E释攑֯obj的锁定后卌取这个锁?<br /> 4) obj.notifyAll()是唤醒所有在obj的wait set中的U程,q批U程在当前线E释放obj的锁定后ȝ争这个锁?最l只有一个能获得,其它的又重新q回wait set{待下一ơ激z?<br /> 5) 执行q个wait,notify和notifyAllq三个方法前,当前U程(x行obj.wait(), obj.notify()和obj.notifyAll()代码的线E?必须持有obj的锁?</p> <img src ="http://www.tkk7.com/junglesong/aggbug/181390.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/junglesong/" target="_blank">junglesong的博?/a> 2008-02-22 14:13 <a href="http://www.tkk7.com/junglesong/archive/2008/02/22/181390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>U程的死?/title><link>http://www.tkk7.com/junglesong/archive/2008/02/22/181388.html</link><dc:creator>junglesong的博?/dc:creator><author>junglesong的博?/author><pubDate>Fri, 22 Feb 2008 06:11:00 GMT</pubDate><guid>http://www.tkk7.com/junglesong/archive/2008/02/22/181388.html</guid><wfw:comment>http://www.tkk7.com/junglesong/comments/181388.html</wfw:comment><comments>http://www.tkk7.com/junglesong/archive/2008/02/22/181388.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/junglesong/comments/commentRss/181388.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/junglesong/services/trackbacks/181388.html</trackback:ping><description><![CDATA[<p><strong>本文内容</strong></p> <p>同步不是改善E序安全性的灵丹妙药?br /> 发生死锁的两U情况和解决Ҏ(gu)?/p> <p><strong>同步不是改善E序安全性的灵丹妙药</strong></p> <p>从《线E的同步》一节中我们可以知道Qsynchronized能保证只有一个线E进入同步方法或同步块,但ؓ了安全性盲目给多线E程序加上synchronized关键字ƈ不是问题解决之道Q这不但会降低程序的效率Q还有可能带来严重的问题-死锁?br /> 死锁发生在两个或以上的线E在{待对象锁被释放Q但E序的环境却让lock无法释放时。下面我们将看到两种cd的死锁例子?/p> <p><strong>某线E不退出同步函数造成的死?/strong></p> <p>public class PaintBoard  extends Thread{<br />   private boolean flag=true;<br />   <br />   public void paint(){    <br />     System.out.println("模拟l画");<br />   }<br />   <br />   public synchronized void run(){<br />     while(flag){<br />       try{<br />         paint();<br />         Thread.sleep(1000);<br />       }<br />       catch(InterruptedException ex){<br />         ex.printStackTrace();<br />       }<br />     }<br />   }<br />   <br />   public synchronized void stopDraw(){<br />     flag=false;<br />     System.out.println("止l画");<br />   }<br />   <br />   public static void main(String[] args){<br />     PaintBoard paintBoard=new PaintBoard();<br />     paintBoard.start();<br />     new StopThread(paintBoard);<br />   }<br /> }</p> <p>public class StopThread implements Runnable{<br />   private PaintBoard paintBoard;<br />   <br />   public StopThread(PaintBoard paintBoard){<br />     this.paintBoard=paintBoard;<br />     <br />     Thread th=new Thread(this);<br />     th.start();<br />   }<br />   <br />   public void run(){<br />     while(true){<br />       System.out.println("试图停止l画q程");<br />       paintBoard.stopDraw();<br />       System.out.println("停止l画q程完成");<br />     }<br />   }<br /> }</p> <p><strong>问题的发生和解决</strong></p> <p>刚才的死锁原因是run()函数中有一个无限@环,一个线E进入后会在其中往复操作,q它永q不会放弃对this的锁定,l果D其它U程无法获得this的锁定而进入stopDraw函数?br /> 我们把修饰run函数的synchronized取消p解决问题?run函数中不会改变Q何量Q这U函数是不该加上synchronized的?/p> <p>两个U程争抢资源造成的死?</p> <p>public class Desk{<br />   private Object fork=new Object();<br />   private Object knife=new Object();<br />   <br />   public void eatForLeft(){<br />     synchronized(fork){<br />       System.out.println("左撇子拿起叉");<br />       sleep(1);<br />       synchronized(knife){<br />         System.out.println("左撇子拿起刀");<br />         System.out.println("左撇子开始吃?);<br />       }<br />     }<br />   }<br />   <br />   public void eatForRight(){<br />     synchronized(knife){<br />       System.out.println("x子拿起刀");<br />       sleep(1);<br />       synchronized(fork){<br />         System.out.println("x子拿起叉");<br />         System.out.println("x子开始吃?);<br />       }<br />     }<br />   }<br />   <br />   private void sleep(int second){<br />     try{<br />       Thread.sleep(second*1000);<br />     }<br />     catch(InterruptedException ex){<br />       ex.printStackTrace();<br />     }<br />   }<br />   <br />   public static void main(String[] args){<br />     Desk desk=new Desk();<br />     new LeftHand(desk);<br />     new RightHand(desk);<br />   }<br /> }</p> <p>public class LeftHand implements Runnable{<br />   private Desk desk;<br />   <br />   public LeftHand(Desk desk){<br />     this.desk=desk;<br />     <br />     Thread th=new Thread(this);<br />     th.start();<br />   }<br />   <br />   public void run(){<br />     while(true){<br />       desk.eatForLeft();<br />     }<br />   }<br /> }</p> <p>public class RightHand implements Runnable{<br />   private Desk desk;<br />   <br />   public RightHand(Desk desk){<br />     this.desk=desk;<br />     <br />     Thread th=new Thread(this);<br />     th.start();<br />   }<br />   <br />   public void run(){<br />     while(true){<br />       desk.eatForRight();<br />     }<br />   }<br /> }</p> <p><strong>问题的发生和解决</strong></p> <p>q部分程序中于两个线E都要获得两个对象的锁定才能执行实质性操作,但运行v来却发现其它U程持有了自己需要的另一个锁定,于是停在Wait Set中等待对斚w放这个锁定,l果造成了死锁?br /> 解决q个问题的方法是保证锁对象的持有序Q如果两个加上了同步的函数都是先刀后叉的Ş式则不会发生问题?/p> <p><strong>结</strong></p> <p>同步不是改善E序安全性的灵丹妙药Q盲目同步也会导致严重的问题-死锁.<br /> 某线E持l不退出同步函C造成死锁.解决Ҏ(gu)是去掉或更换不正的同步?br /> 两个U程都等待对斚w放自己需要的资源也会造成死锁.q种情况的解x法是保同步锁对象的持有序?/p> <img src ="http://www.tkk7.com/junglesong/aggbug/181388.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/junglesong/" target="_blank">junglesong的博?/a> 2008-02-22 14:11 <a href="http://www.tkk7.com/junglesong/archive/2008/02/22/181388.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>U程的互?/title><link>http://www.tkk7.com/junglesong/archive/2008/02/22/181358.html</link><dc:creator>junglesong的博?/dc:creator><author>junglesong的博?/author><pubDate>Fri, 22 Feb 2008 04:43:00 GMT</pubDate><guid>http://www.tkk7.com/junglesong/archive/2008/02/22/181358.html</guid><wfw:comment>http://www.tkk7.com/junglesong/comments/181358.html</wfw:comment><comments>http://www.tkk7.com/junglesong/archive/2008/02/22/181358.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/junglesong/comments/commentRss/181358.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/junglesong/services/trackbacks/181358.html</trackback:ping><description><![CDATA[<p><strong>多线E操作同一实例的问?/strong></p> <p>在多U程环境中,l常有两个以上线E操作同一实例的问题,无论是ƈ行Parallel环境q是q发Concurrent环境Q都有发生有多个U程修改同一变量的问题,如果q个变量是成员变量,多线E将会给E序带来破坏性的影响。请见以下代码?/p> <p><strong>资源库类</strong></p> <p>public class ResourceLib {<br />   private long count1;</p> <p>  private long count2;</p> <p>  public ResourceLib(int count) {<br />     this.count1 = count;      <br />     this.count2 = count;<br />   }</p> <p>  /**<br />    * 取回资源<br />    * 加上synchronized才是U程安全<br />    * <br />    * @param count<br />    */<br />   public void fetch(int count) {<br />     count1 += count;    <br />     mockLongTimeProcess();    <br />     count2 += count;    <br />     checkTwoCount(count);<br />   }</p> <p>  /**<br />    * 送出资源<br />    * 加上synchronized才是U程安全<br />    * <br />    * @param count<br />    * @return<br />    */<br />   public void send(int count) {<br />     count1 -= count;    <br />     mockLongTimeProcess();    <br />     count2 -= count;<br />     checkTwoCount(count);<br />   }</p> <p>   /**<br />    * 模拟一个耗时q程<br />    *<br />    */<br />   private void mockLongTimeProcess(){<br />     try{<br />       Thread.sleep(1000);<br />     }<br />     catch(Exception ex){<br />       ex.printStackTrace();<br />     }<br />   }</p> <p>  private void checkTwoCount(int borrowCount) {<br />     if (count1 != count2) {<br />       System.out.println(count1 + "!= " + count2);<br />       System.exit(0);<br />     } else {<br />       System.out.println(count1 + "==" + count2);<br />     }<br />     <br />     if (Math.abs(count1) > 10000000 || Math.abs(count2) > 10000000) {<br />       count1 = 0;<br />       count2 = 0;<br />     }<br />   }</p> <p>  public static void main(String[] args) {<br />     ResourceLib lib = new ResourceLib(10000);</p> <p>    for (int i = 1; i < 20; i++) {<br />       new Supplier(String.valueOf(i), i, lib);<br />     }</p> <p>    for (int i = 1; i < 10; i++) {<br />       new Comsumer(String.valueOf(i), i, lib);<br />     }<br />   }<br /> }</p> <p><strong>取资源和l资源的两个U程</strong></p> <p>public class Comsumer implements Runnable{<br />   private ResourceLib resourceLib;<br />   private int count;<br />   <br />   public Comsumer(String name,int count,ResourceLib resourceLib){<br />     this.count=count;<br />     this.resourceLib=resourceLib;<br />     <br />     Thread thread=new Thread(this);<br />     thread.start();<br />   }<br />   <br />   public void run(){<br />     while(true){<br />       resourceLib.send(count);<br />     }<br />   }<br /> }</p> <p>public class Supplier implements Runnable{<br />   private ResourceLib resourceLib;<br />   private int count;<br />   <br />   public Supplier(String name,int count,ResourceLib resourceLib){<br />     this.count=count;<br />     this.resourceLib=resourceLib;<br />     <br />     Thread thread=new Thread(this);<br />     thread.start();<br />   }<br />   <br />   public void run(){<br />     while(true){<br />       resourceLib.fetch(count);<br />     }<br />   }<br /> }</p> <p><strong>q行l果</strong></p> <p>在main函数中,E序启动了多个消费者线E和生者线E,消费者线E在不断减少count1和count2Q生产者线E在不断增加count1和count2Q在单线E环境中Q程序绝不会出现count1和count2不相{的情况Q而多U程环境中,可能有一个线E在查count1和count2Ӟ其中一个已l被另一个线E所修改?br /> 因此D了两个g相等的情况发生?/p> <p>q行l果之一<br /> 10145!= 10001<br /> 10145!= 10003<br /> 10145!= 10006<br /> 10145!= 10010<br /> 10145!= 10015<br /> 10145!= 10021<br /> 10145!= 10028<br /> 10145!= 10036<br /> 10145!= 10045<br /> 10145!= 10055<br /> 10145!= 10066</p> <p><strong>另一个经典多U程实例Q银行取?/strong></p> <p>package com.sitinspring.unsafebank;</p> <p>public class Bank{<br />   private int count;<br />   <br />   public Bank(int count){<br />     this.count=count;<br />   }<br />   <br />   public void withdraw(int money){<br />     if(count>money){<br />       mockLongTimeProcess();// 模拟耗时q程<br />       count-=money;<br />       System.out.println("提走"+money+" 现有"+count);     <br />     }<br />     else{<br />       System.out.println(" 现有数量"+count+"于"+money+" 不能提取");<br />     }<br />     <br />     checkCount();<br />   }<br />   <br />   public void checkCount(){<br />     if(count<0){<br />       System.out.println(count + "< 0 ");<br />       System.exit(0);<br />     }<br />   }</p> <p> /**<br />    * 模拟一个耗时q程<br />    *<br />    */<br />   private void mockLongTimeProcess(){<br />     try{<br />       Thread.sleep(1000);<br />     }<br />     catch(Exception ex){<br />       ex.printStackTrace();<br />     }<br />   }<br />   <br />   public static void main(String[] args){<br />     Bank bank=new Bank(1000);<br />     <br />     for(int i=1;i<10;i++){<br />       new Customer(i*i*i,bank);<br />     }<br />   }<br /> }</p> <p><strong>客户cd讲述</strong></p> <p>public class Customer implements Runnable{<br />   private Bank bank;<br />   private int count;<br />   <br />   public Customer(int count,Bank bank){<br />     this.count=count;<br />     this.bank=bank;<br />     <br />     Thread thread=new Thread(this);<br />     thread.start();<br />   }<br />   <br />   public void run(){<br />     while(true){<br />       bank.withdraw(count);<br />     }<br />   }<br /> }</p> <p>在单U程环境中,提款旉行的Ll不会是负数Q但在多U程环境中,有可能在一个线EAW合条g在进行耗时q算和网l数据传递时Q另一个线EB已经把钱提走QL已经发生变化Q结果AU程再提ƾ时总钱数已l减了Q因此致佉K行总钱数小于零?/p> <p><strong>解决Ҏ(gu)Q在Ҏ(gu)员变量进行修改的函数前加上synchronized关键?/strong></p> <p>synchronizedҎ(gu)又被成ؓ”同步“Ҏ(gu)。当一个方法加上关键字synchronized声明之后Q就可以让一个线E操作这个方法?#8220;让一个线E操?#8221;q不是说只能让某一个特定的U程操作而已Q而是指一ơ只能让一个线E执行,也就是说,在一个线E没有退出同步方法前Q其它线E绝无可能进入这个同步方法和其它q列的同步方法,只能在外面排队等候?br /> 一个实例的synchronizedҎ(gu)只能允许1ơ一个线E执行。但是非synchronizedҎ(gu)没有这个限Ӟ它可以供2个以上的U程执行?/p> <p><strong>修改后的U程安全的Bankc?/strong></p> <p>public class Bank{<br />   private int count;<br />   <br />   public Bank(int count){<br />     this.count=count;<br />   }<br />   <br />   public synchronized void withdraw(int money){<br />     if(count>money){<br />       mockLongTimeProcess();// 模拟耗时q程<br />       count-=money;<br />       System.out.println("提走"+money+" 现有"+count);     <br />     }<br />     else{<br />       System.out.println(" 现有数量"+count+"于"+money+" 不能提取");<br />     }<br />     <br />     checkCount();<br />   }<br />   <br />   public void checkCount(){<br />     if(count<0){<br />       System.out.println(count + "< 0 ");<br />       System.exit(0);<br />     }<br />   }<br /> 。。。?/ 部分代码省略<br /> }<br /> </p> <p><strong><img height="546" alt="" src="http://www.tkk7.com/images/blogjava_net/junglesong/threadconlfict1.jpg" width="411" border="0" /><br /> <br /> 修改后的U程安全的ResourceLibc?/strong></p> <p>public class ResourceLib {<br />   private long count1;<br />   private long count2;</p> <p>  public synchronized void fetch(int count) {<br />     count1 += count;    <br />     mockLongTimeProcess();    <br />     count2 += count;    <br />     checkTwoCount(count);<br />   }</p> <p>  public synchronized void send(int count) {<br />     count1 -= count;    <br />     mockLongTimeProcess();    <br />     count2 -= count;<br />     checkTwoCount(count);<br />   }</p> <p>  public void checkTwoCount(int borrowCount) {<br />     if (count1 != count2) {<br />       System.out.println(count1 + "!= " + count2);<br />       System.exit(0);<br />     } else {<br />       System.out.println(count1 + "==" + count2);<br />     }<br />     <br />     if (Math.abs(count1) > 10000000 || Math.abs(count2) > 10000000) {<br />       count1 = 0;<br />       count2 = 0;<br />     }<br />   }<br /> }</p> <p>?部分代码省略<br /> </p> <p><strong><img height="541" alt="" src="http://www.tkk7.com/images/blogjava_net/junglesong/threadconlfict2.jpg" width="424" border="0" /><br /> <br /> 执行之后</strong></p> <p>在一个执行synchronizedҎ(gu)的线E执行结束后,锁定卌释放, 其它不得光而入的线E开始争抢锁?一定会有一个线E获取锁?没有抢到的线E只好再l箋{?<br /> 注意: 非静态的synchronizedҎ(gu)锁定的对象是实例Q静态的synchronizedҎ(gu)锁定的对象是cd象?/p> <p><strong>同步?/strong></p> <p>以下同步Ҏ(gu)可用双的同步块代替:<br /> public synchronized void fun(){<br />     ………<br /> }</p> <p>与左边同步方法对{的同步块:<br /> public void fun(){<br />    synchronized(this){<br />      ………<br />    }<br /> }</p> <p><strong>同步块和同步Ҏ(gu)的比?/strong></p> <p>1Q同步方法锁定的cȝ实例或类对象Q同步块则可以换成Q意实例,灉|性更高?br /> 2Q有旉要多个锁定而不是一个,如函数A和函数B需要锁?Q函数B和函数C需要锁?Q这时如果用同步方法无疑会锁定A和CQ造成E序效率的降低。这时最应该使用同步块?/p> <p><strong>什么时候该加同步synchronized</strong></p> <p>如果一个函数或代码块有可能被多个线E进入,而这个函数或代码块又修改了类的成员变量,则这个这个函数或代码块就应该加上同步synchronized?br /> 如果一个函数或代码有可能被多个U程q入Q而这个函数或代码块只是读取类的成员变量,则这个这个函数或代码块就不该加上同步synchronized?/p> <p> </p> <img src ="http://www.tkk7.com/junglesong/aggbug/181358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/junglesong/" target="_blank">junglesong的博?/a> 2008-02-22 12:43 <a href="http://www.tkk7.com/junglesong/archive/2008/02/22/181358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>U程的创?/title><link>http://www.tkk7.com/junglesong/archive/2008/02/22/181356.html</link><dc:creator>junglesong的博?/dc:creator><author>junglesong的博?/author><pubDate>Fri, 22 Feb 2008 04:34:00 GMT</pubDate><guid>http://www.tkk7.com/junglesong/archive/2008/02/22/181356.html</guid><wfw:comment>http://www.tkk7.com/junglesong/comments/181356.html</wfw:comment><comments>http://www.tkk7.com/junglesong/archive/2008/02/22/181356.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/junglesong/comments/commentRss/181356.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/junglesong/services/trackbacks/181356.html</trackback:ping><description><![CDATA[<p><strong>单线E程?/strong></p> <p>一般来_在没有线E的帮助下,E序在一个时间段只能执行一D代码,其它代码D只有在{待它完成后才能执行。该E序的处理流E从头到֏有一条线Q这L(fng)E序我们UC为单U程E序QSingle Thread ProgramQ?/p> <p>典型的单U程E序Q?br /> public class SingleThreadProgram{<br />   public static void main(String[] args){<br />     for(int i=0;i<1000;i++){<br />       System.out.print("SingleThreadProgram");<br />     }<br />   }<br /> }</p> <p><strong>多线E程?/strong></p> <p>当程序由一个以上的U程所构成ӞU此E序为多U程E序QMultithread ProgramQ,java从设计伊始就把程序的多线E能力列入了考虑范围?br /> 典型的多U程E序有:</p> <p>1QGUI应用E序Q我们目前做的Swing桌面E序属于此cR?br /> 2Q较p旉的I/O处理,一般来?文g和网l的输入/输出处理比较p旉,如果在这D|法进行其它处?则程序性能会大打折?遇到q种情况首先要想到用多线E解决问?<br /> 3Q多q接|络处理?/p> <p><strong>q发(Concurrent)与ƈ?Parallel)</strong></p> <p>当有多个U程在操作时,如果pȝ只有一个CPU,则它Ҏ(gu)不可能真正同时进行一个以上的U程,它只能把CPUq行旉划分成若q个旉D?再将旉D分配给各个U程执行,在一个时间段的线E代码运行时,其它U程处于挂v状?q种方式我们UC为ƈ?Concurrent).<br /> 当系l有一个以上CPU?则线E的操作有可能非q发.当一个CPU执行一个线E时,另一个CPU可以执行另一个线E?两个U程互不抢占CPU资源,可以同时q行,q种方式我们UC为ƈ?Parallel)<br /> </p> <p><img height="514" alt="" src="http://www.tkk7.com/images/blogjava_net/junglesong/concurrentparalel.jpg" width="652" border="0" /><br /> <br /> <strong>多线E在q发和ƈ行环境中的不同作?/strong></p> <p>在ƈ发环境时,多线E不可能真正充分利用CPU,节约q行旉,它只是以”挂v->执行->挂v”的方式以很小的时间片分别q行各个U程,l用户以每个U程都在q行的错?在这U环境中,多线E程序真正改善的是系l的响应性能和程序的友好?<br /> 在ƈ行环境中, 一个时d许多个线E运?q时多线E程序才真正充分利用了多CPU的处理能? 节省了整体的q行旉.在这U环境中,多线E程序能体现出它的四大优?充分利用CPU,节省旉,改善响应和增加程序的友好?</p> <p>PS:在多核时代来临后,开发多U程E序的能力更是每个程序员都该具备?</p> <p><strong>创徏多线E程?/strong></p> <p>创徏多线E程序我们通常有两U方法:<br /> 1Q让cȝ承java.lang.Thread,q种Ҏ(gu)优势在于调用E微方便,一般用于后台批处理E序的场?但劣势是cL法再l承别的cR?br /> 2Q让cd现接口java.lang.RunnableQ这U方法调用时需要借助Thread的帮助,E显ȝQ但优势在于对类l承体系没有影响Q这是用线E时最常用的方法?br /> 两种Ҏ(gu)的线E执行部分都在runQ)函数中,它们的效率没有差别?/p> <p><strong>多线E程序创建和启动CZ</strong></p> <p>创徏U程</p> <p>// l承Threadc?br /> public class Thread1 extends Thread{<br />   public void run(){<br />     while(true){<br />       System.out.println("<Thread1 extends Thread>");<br />     }<br />   }<br /> }</p> <p>// 实现Runnable接口<br /> public class Thread2 implements Runnable{<br />   public void run(){<br />     while(true){<br />       System.out.println("<Thread2 implements Runnable>");<br />     }<br />   }<br /> }</p> <p>启动U程</p> <p>public class Main{<br />   public static void main(String[] args){<br />     // 启动U程1,Thread1直接l承自java.lang.Threadc?br />     Thread1 th1=new Thread1();<br />     th1.start();<br />     <br />     // 启动U程2Qthread2实现自java.lang.Runnable接口<br />     Thread2 thread2=new Thread2();<br />     Thread th2=new Thread(thread2);<br />     th2.start();<br />     <br />     while(true){<br />       System.out.println("<Main Thread>");<br />     }<br />   }<br /> }</p> <p><strong>概念解析Start和Run</strong></p> <p>public void run()<br /> q个函数容纳U程启动后执行的代码?U程启动h,run函数中的代码会得到执?</p> <p>Thead.start()<br /> q是启动一个线E的Ҏ(gu),调用了这个方法后,U程才会得到执行.</p> <p><strong>取得U程执行的结?/strong></p> <p>通过观察run函数的签名public void run()我们可以发现,它既没有输入参数,也没有返回?那如何取得线E的q回值呢?一般来说我们有三种办法:<br /> 1)让线E修改公有变?如某cȝ静态公有字D?q种方式古老而危?最好不要采?<br /> 2)轮询U程执行l果,U程执行的结果放在线E类的一个字D中,外界不断通过轮询L看执行结?q种方式会浪费很多时?l果也不可靠,不徏议采?<br /> 3)回调方式,把调用方的指针通过U程cȝ构造函C入线E类的一个字D中,当线E执行完取得l果后再通过q个字段反向调用调用方的函数.q是取得U程执行l果的最佌x?</p> <p>下面L(fng)<strong>回调方式的实?/strong>.</p> <p>Bossc?br /> q个cȝ于启动SecretaryU程L找文? findFile()是启动线Eƈ查找的函? giveBossResult(String file,String reult)是供Secretarycd调的函数.</p> <p>public class Boss{<br />   private String name;<br />   <br />   public Boss(String name){<br />     this.name=name;<br />   }<br />   <br />   public void giveBossResult(String file,String reult){<br />     if(reult!=null){<br />       System.out.println("文g"+file+"序列L(fng)于:"+reult);<br />     }<br />     else{<br />       System.out.println("无法扑ֈ文g"+file);<br />     }<br />   }<br />   <br />   public void findFile(){   <br />     Map<String,String> files=new Hashtable<String,String>();    <br />     files.put("001", "员工花名?);<br />     files.put("002", "企业收支");<br />     files.put("003", "客户花名?);<br />     files.put("004", "Ҏ(gu)状况分析");<br />     files.put("005", "当月收支");<br />     files.put("006", "市场份额分析");<br />     files.put("007", "大连酒店一?);<br />     files.put("008", "׃场所名录");<br />     files.put("009", "关系单位联系名录");<br />     <br />     Secretary andy=new Secretary("Andy",this,"员工花名?,files);<br />     Thread th1=new Thread(andy);<br />     th1.start();<br />     <br />     Secretary cindy=new Secretary("cindy",this,"上市情况分析",files);<br />     Thread th2=new Thread(cindy);<br />     th2.start();<br />   }<br />   <br />   public static void main(String[] args){<br />     Boss boss=new Boss("Bill");<br />     boss.findFile();<br />   }<br /> }</p> <p>Secretaryc?/p> <p>q个cLq行多线E查找文件的c?查找的结果通过回调Ҏ(gu)告知Boss实例.<br /> Boss实例,查找的文件名,查找的集合都通过Secretarycȝ构造函Cq来.</p> <p>public class Secretary implements Runnable{<br />   private String name;<br />   private Boss boss;<br />   private String file;<br />   private Map<String,String> files;<br />   <br />   public Secretary(String name,Boss boss,String file,Map<String,String> files){<br />     this.name=name;<br />     this.boss=boss;<br />     this.file=file;<br />     this.files=files;<br />   }<br />   <br />   public void run(){<br />     for(Map.Entry<String,String> entry:files.entrySet()){<br />          if(entry.getValue().equals(file)){<br />            boss.giveBossResult(file,entry.getKey());<br />            return;<br />          }<br />     }<br />     <br />     boss.giveBossResult(file,null);<br />   }<br /> }</p> <img src ="http://www.tkk7.com/junglesong/aggbug/181356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/junglesong/" target="_blank">junglesong的博?/a> 2008-02-22 12:34 <a href="http://www.tkk7.com/junglesong/archive/2008/02/22/181356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://0769wwt.com" target="_blank">ĻƬ</a>| <a href="http://www-44455588.com" target="_blank">޹ƷƬþ </a>| <a href="http://www-533999.com" target="_blank">ԸŮƵվҹ</a>| <a href="http://6464k.com" target="_blank">޾Ʒ߹ۿ</a>| <a href="http://www961dd.com" target="_blank">ؼƷëƬѹۿ</a>| <a href="http://bbby6.com" target="_blank">AVŮһ</a>| <a href="http://zhaoav7.com" target="_blank">ѵȫһ¼</a>| <a href="http://xjscr.com" target="_blank">Ƶ߹ۿһ</a>| <a href="http://jcthbank.com" target="_blank">þþøƵ</a>| <a href="http://xiamenwave.com" target="_blank">һŷһ</a>| <a href="http://zhuguangbaoyu.com" target="_blank">ҹһëƬ</a>| <a href="http://18yinren.com" target="_blank">aƬձþ</a>| <a href="http://xmllhb.com" target="_blank">޹ӰԺ</a>| <a href="http://meyume.com" target="_blank">ɫˬƵ</a>| <a href="http://jmdehong.com" target="_blank">޹˾þۺ3d </a>| <a href="http://bdyls.com" target="_blank">ĻȫƵ </a>| <a href="http://sdzsx.com" target="_blank">fuli߹ۿ</a>| <a href="http://igdytt.com" target="_blank">պƵ</a>| <a href="http://yw8885.com" target="_blank">ݹѹۿ</a>| <a href="http://yuezhaoming.com" target="_blank">ĻþþƷAPP</a>| <a href="http://aiqingdao999.com" target="_blank">һ</a>| <a href="http://19520888.com" target="_blank">þAVӰ</a>| <a href="http://www-bajie.com" target="_blank">þùƵ</a>| <a href="http://yy9977.com" target="_blank">Ƶվ߲</a>| <a href="http://znboxcdn304.com" target="_blank">þ99ۺϾƷҳ</a>| <a href="http://chiguigu.com" target="_blank">þһҰ</a>| <a href="http://jldledu.com" target="_blank">޸Ůһ</a>| <a href="http://wwyw99977.com" target="_blank">2019Ļ</a>| <a href="http://js06vip.com" target="_blank">ӰӴȫ߲</a>| <a href="http://xfmkt.com" target="_blank">þùƷۺ</a>| <a href="http://wwwhaole10.com" target="_blank">Ů糱ëƬѲ</a>| <a href="http://bobostrong31.com" target="_blank">һػɫƬ</a>| <a href="http://jioupin.com" target="_blank">޾Ʒվ</a>| <a href="http://527352.com" target="_blank">AƵһ</a>| <a href="http://959901cc.com" target="_blank">99reƵ</a>| <a href="http://8xcb.com" target="_blank">߳ëƬڵƵ</a>| <a href="http://yw762.com" target="_blank">sɫƬ߹ۿ</a>| <a href="http://22nee.com" target="_blank">Ѹavһ</a>| <a href="http://hljc988.com" target="_blank">˹ƷƵ</a>| <a href="http://51wdn.com" target="_blank">һ߹ۿ</a>| <a href="http://dqcjlb.com" target="_blank">ҹƵ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>