现在的位置: 首页 > 综合 > 正文

多线程的应用 多线程

2018年08月14日 ⁄ 综合 ⁄ 共 4647字 ⁄ 字号 评论关闭

 

 

多线程的应用:
1.网络聊天工具开发
  一个线程负责发消息,一个负责收消息。两者互不干扰,如果是单线程,那么就可能前面在等待,而后面就接收不了消息。
2.大量数据库记录的复制。
  如果一个复制要花3天时间,那么当你中途觉得没有必要,要停止的时候,你发现你不能让他停下来。而多线程的情况,一个
  现成负责拷贝,是个无限循环
  while(bStop)
  {get data
   copy data}
  另一个现成监督是否有键盘按下,也就是把原本为true的变量bstop置为false。   bStop = false;当另一线程监视到变量  变化时会停止程序
3.www服务器为每一个来访者创建一个线程

一个线程必须处于如下四种可能的状态之一,这四种状态为:

初始态:一个线程调用了new方法之后,并在调用start方法之前的所处状态。在初始态中,可以调用start和stop方法。
Runnable:一旦线程调用了start 方法,线程就转到Runnable 状态,注意,如果线程处于Runnable状态,它也有可能不在运行,这是因为还有优先级和调度问题。

阻塞/ NonRunnable:线程处于阻塞/NonRunnable状态,这是由两种可能性造成的:要么是因挂起而暂停的,要么是由于某些原因而阻塞的,例如包括等待IO请求的完成。

退出:线程转到退出状态,这有两种可能性,要么是run方法执行结束,要么是调用了stop方法。

 

 

 

 

 

 

多线程
 

1.程序是计算机指令的集合,它以文件的形式存储在磁盘上。

                         进程:是一个程序在其自身的地址空间中的一次执行活动。

                         进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立的运行的单位,因此,它不占用系统的运行资源。

                         线程:是进程中的一个单一的连续控制流程。一个进程可以拥有多个线程。

                         线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。

2.java对多线程的支持

                      java在语言级提供了对多线程程序设计的支持。

                      实现多线程程序的两种方式:

                     (1)从Thread类继承;

                     (2)实现Runnable接口。

                       例子:

                                public class ThreadTest {

                                 /**
                                 * @param args
                                 */
                                       public static void main(String[] args) {
                                             MyThread myThread = new MyThread();
                                             myThread.start();
                                             System.out.println("main:" + Thread.currentThread().getName());
                                       }

                                 }

                                 class MyThread extends Thread{

                                        public void run(){
                                               System.out.println(getName());
                                        }
                                 }

                           打印的结果:main:main
                                                Thread-0

                           为什么先执行 myThread.start()而打印的是main:main?因为程序开始调用的cpu将时间片分配给main函数,而此时开启另一个MyThread的线程时,cpu分配给main函数所在线程的时间片并未到期,故main函数执行完System.out.println("main:" + Thread.currentThread().getName())后,MyThread的线程才开始执行属于cpu分配给它的时间片。

                      后台线程: 当程序中只剩下后台线程时,java虚拟机就退出了。也就是说一个进程中没有非后台进程运行时,那么java虚拟机就要退出了。

                      当要设置线程为后台线程时,用Thread类中的setDaemon()方法,该方法必须在start()方法之前被调用。

2.线程暂停

                     Thread类中的yield()方法可以让当前线程暂停,转而让其他线程执行。

3.线程优先级

                     Thread类中的setPriority()和getPriority()方法可以设置和得到线程的优先级。

                     Thread类中的线程优先级有3种MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY,它们的类型为int,其值分别为10、1、5。设置优先级不一定要在start()方法前进行,可以随时修改线程的优先 级。在java中一个线程的优先级较高,它将始终获得执行的机会。

                     java是不支持线程时间片轮换的调度模型,而采用的是线程优先级高低的抢占调度模型。具有高优先级的线程可以抢占低优先级线程运行的机会。高优先级的线程将始终获得线程执行时间。但是这也不是绝对的,java线程调度器有可能会调用长期处于等待的线程进行执行,所以不要依靠线程的高优先级抢占模型去完成某些功能。

                  java线程调度器支持不同优先级线程的抢先方式,但其本身不支持相同优先级线程的时间片轮换。但是如果java运行时系统所在的操作系统(如windows2000)支持时间片的轮换,则线程调度器就支持相同优先级线程的时间片轮换。          

4.用实现Runnable接口的方式调用线程

package com;

public class MultiThread
{
public static void main(String[] args)
{
           MyThread mt=new MyThread();
           new Thread(mt).start();
           while(true)
           {
            System.out.println("main:"+Thread.currentThread().getName());
           }
}
}

class MyThread implements Runnable
{
public void run()
{
           while(true)
           {
            System.out.println(Thread.currentThread().getName());
   
           }
}
}

5.什么时候需要从Runnable接口实现run()方法,什么时候需要从Thread类去派生,来实现多线程?

              通常情况下,我们并不需要去修改除了run()方法之外的其他方法的行为,最好都是去实现Runnable接口。它有两个好处:

               (1)当一个类继承了一个类后,当这个只能用实现Runnable接口的方式来产生线程类对象。

               (2)当用实现Runnable接口的方式来产生线程类对象时,可以达到使多个线程类对象功用同一个变量的目的。

6. 线程的同步

              同步的两种方式:同步块和同步方法

             (1)对于同步块来说,我们需要在synchronized后加一个对象,这个对象是一个任意的对象。

             (2)每一个对象都有一个监视器,或者叫做锁。

              (3)同步方法利用的是this所代表的对象的锁。

              (4)每个class也有一个锁,是这个class所对应的Class对象的锁。我们同步静态方法就是同步这个class所对应的Class对象的监视器。

7.线程的死锁

            (1)哲学家进餐的问题

            (2)线程1锁住了对象A的监视器,等待对象B的监视器,线程2锁住了对象B的监视器,等待对象A的监视器,就造成了死锁。

            ●suspend和resume方法容易造成死锁,不建议使用。

8.wait、notify、notifyAll

        (1)每一个对象除了有一个锁之外,还有一个等待队列(wait set),当一个对象刚创建的时候,它的等待队列是空的。

        (2)我们应该在当前线程锁住对象的锁后,去调用该对象的wait方法。(说明wait方法只能在同步块和同步方法中被调用。当调用wait方法的时候,我们这个线程就进入了这个对象的等待队列当中。)

        (3)当调用对象的notify方法时,将从该对象的等待队列中删除一个任意选择的线程,这个线程将再次成为可运行的线程。(notify方法只能在同步块和同步方法中被调用)

        (4)当调用对象的notifyAll方法时,将从该对象的等待队列中删除所有等待的线程,这些线程将成为可运行的线程。

        (5)wait和notify主要用于producer-consumer这种关系中。

        ●使用wait和notify方法时,必须是对同一个对象的等待队列进行操作。

9.线程的终止

       (1)设置一个flag变量。

       (2)结合interrupt()方法。

 

 

 

 

 

 

 

 

抱歉!评论已关闭.