论坛首页 Java版

Java多线程

浏览 1011 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (11) :: 隐藏帖 (0)
作者 正文
时间:2008-03-29 关键字: java 多线程

最近还是比较忙,总算音乐模块歌词部分的开发任务基本搞定,今天不用加班了,再说今天北京下雨了,不用去公司啦,感觉在J2ME开发中线程知识台重要了,今天把线程部分仔细看了下。

进程:是一个程序在其自身地址空间的一次执行活动,进程是资源申请、调度和独立运行的单位,因此他使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此它不占用系统的运行资源。

线程:是程序中的一个单一的连续控制流程,一个线程可以拥有多个线程 。记得刚学习Java的时候,对线程中的run()不知道是什么意思,现在大胆认为它就像Javamain()一样,可以理解为一个线程启动运行的入口函数。

创建一个线程的方式有两种,一种是继承Thread类,还有就是实现Runnable 接口,两者都要重写run()方法。如下:

class MyThread extends Thread {

public void run(){}
}
或者

class MyThread implements Runnable{

         public void run(){};

}

对了,Every thread has a priority. Threads with higher priority are executed in preference to threads with lower priority.线程的静态变量MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY其值分别是1015不信自己打印出来看。我们创建一个线程默认的优先级是5,我们在设置线程的优先级的范围显然是1-10。我们可以在多个线程同时运行的时候如何让操作系统将当前时间偏分给我们想要执行的线程时,可以将该线程的优先级设置Thread.MAX_PRIORITY . 

下面是一个生产者和消费者的多线程的例子:其规则很简单,只有生产出来东西才能有东西来消费。知识点:线程的创建、线程的同步、顺便回顾一下大学的操作系统。

class Test {

    public static void main(String[] args) {

        Queue q = new Queue();

        Producer p = new Producer(q);

        Consumer c = new Consumer(q);

        p.start();

        c.start();

    }

}

 

class Producer extends Thread {

    Queue q;

    Producer(Queue q) {

        this.q = q;

    }

    public void run() {

        for (int i = 0; i < 10; i++) {

            q.put(i);

            System.out.println("Producer put " + i);

        }

    }

}

  

class Consumer extends Thread {

    Queue q;

    Consumer(Queue q) {

        this.q = q;

    }

 

    public void run() {

        while (true) {

            System.out.println("Consumer get " + q.get());

        }

    }

}

 

class Queue {

    int value;

    boolean bFull = false;

    public synchronized void put(int i) {

        if (!bFull) {

            value = i;

            bFull = true;

            notify();

        }

        try {

            wait();

        } catch (Exception e) {

            e.printStackTrace();

        }

 

    }

 

    public synchronized int get() {

        if (!bFull) {

            try {

                wait();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

        bFull = false;

        notify();

        return value;

    }

}

上面的例子只是一个很普遍的例子,在j2me中的运用如:基于c/s结构的发送请求和接受请求响应就是一个运用很广泛的实列。

Java多线程一个很重要的关键字就是线程同步synchronized,下面的火车票的售票系统的模型:同步分同步块和同步方法:

class SellThread implements Runnable

{

         int tickets=100;

         Object obj=new Object();

         boolean b=false;

         public void run()

         {

                   if(b==false)

                   {

                            while(true)

                                     sell();

                   }

                   else

                   {

                            while(true)

                            {

                                     synchronized(obj)

                                     {

                                               try

                                               {

                                                        Thread.sleep(10);

                                               }

                                               catch(Exception e)

                                               {

                                                        e.printStackTrace();

                                               }

                                               synchronized(this)

                                               {

                                                        if(tickets>0)

                                                        {

                                                                

                                                                 System.out.println("obj:"+Thread.currentThread().getName()+

                                                                                    " sell tickets:"+tickets);

                                                                 tickets--;

                                                        }

                                               }

                                     }

                            }

                   }

         }

         public synchronized void sell()

         {

                   synchronized(obj)

                   {

                            if(tickets>0)

                            {

                                     try

                                     {

                                               Thread.sleep(10);

                                     }

                                     catch(Exception e)

                                     {

                                               e.printStackTrace();

                                     }

                                     System.out.println("sell():"+Thread.currentThread().getName()+

                                                        " sell tickets:"+tickets);

                                     tickets--;

                            }

                   }

         }

}

通过网上资料得知:同步块和同步方法其实本质是一样的:都是对对象枷锁。Java 中每个对象都有一个监视器----锁,同步方法是利用this所代表的对象的锁,同步块利用的是同步块对象本身的锁。

 

线程池:J2ME中没有像在jdk中的那样有现成(包util.concurrent)的线程池直接调用即可,那就得自己写了,下面是编写线程池时值得参考的规则(来自IBMBrian Goetz Quiotix Corp总结):

  • 不要对那些同步等待其它任务结果的任务排队。这可能会导致上面所描述的那种形式的死锁,在那种死锁中,所有线程都被一些任务所占用,这些任务依次等待排队任务的结果,而这些任务又无法执行,因为所有的线程都很忙。
  • 在为时间可能很长的操作使用合用的线程时要小心。如果程序必须等待诸如 I/O 完成这样的某个资源,那么请指定最长的等待时间,以及随后是失效还是将任务重新排队以便稍后执行。这样做保证了:通过将某个线程释放给某个可能成功完成的任务,从而将最终取得 某些进展。
  • 理解任务。要有效地调整线程池大小,您需要理解正在排队的任务以及它们正在做什么。它们是 CPU 限制的(CPU-bound)吗?它们是 I/O 限制的(I/O-bound)吗?您的答案将影响您如何调整应用程序。如果您有不同的任务类,这些类有着截然不同的特征,那么为不同任务类设置多个工作队列可能会有意义,这样可以相应地调整每个池。 
今天就这么多了,吃饭去啦。

 

   
时间:2008-03-30
开始的进程和程序的差别写得有点怪怪的,不如这样写:
程序:可以运行的文件(脚本文件等的程序是解析这个脚本的程序)
进程:运行中的程序
   
0 请登录后投票
时间:2008-03-30
在Struts中初始化Action的时候调用的就是对init()的同步块而不是同步方法,当时考虑的是由于Action是单实例多线程的,所以如果一直是同步方法的话可能会影响到其他的进程来访问该方法,就直接对块给同步了,个人感觉是为了提高其效率!
   
0 请登录后投票
时间:2008-03-31
senbao18 17 小时前
在Struts中初始化Action的时候调用的就是对init()的同步块而不是同步方法,当时考虑的是由于Action是单实例多线程的,所以如果一直是同步方法的话可能会影响到其他的进程来访问该方法,就直接对块给同步了,个人感觉是为了提高其效率!

之所以同步就是为了让多个线程在占用同一资源的时候出现错误,才引入的哦。
呵呵。
   
0 请登录后投票
时间:2008-03-31
LinuxFans 写道
senbao18 17 小时前
在Struts中初始化Action的时候调用的就是对init()的同步块而不是同步方法,当时考虑的是由于Action是单实例多线程的,所以如果一直是同步方法的话可能会影响到其他的进程来访问该方法,就直接对块给同步了,个人感觉是为了提高其效率!

之所以同步就是为了让多个线程在占用同一资源的时候出现错误,才引入的哦。
呵呵。

咦?之所以同步不是   "为了避免多个资源占据访问资源的时候出现错误 "   才同步的吗?

   
0 请登录后投票
时间:2008-03-31
我觉得应该是,要不然没有必要啦.
   
0 请登录后投票
时间:2008-03-31
LinuxFans 写道
我觉得应该是,要不然没有必要啦.
呵呵,我和你想的一样,就是避免产生共享资源的线程问题,所以才加上同步块的~~

 

   
0 请登录后投票
论坛首页 Java版

跳转论坛: