多线程的总结

来源:互联网 发布:广告动画制作软件 编辑:程序博客网 时间:2024/06/14 17:32
第一节总结

多线程

多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。



多线程的优势:

1.提高界面程序的响应速度.

2.充分利用系统资源.



在线程编程中,继承Thread类或实现Runnable接口的类才具备多线程的能力。





线程的生命周期与主要的线程状态:

1.    新建状态(New).

2.    就绪状态(Runnable).

3.    运行状态(Run).

4.    阻塞状态(Block).

5.    终止状态(Dead).



线程的优先级用1~10表示,1表四优先级最高,默认值是5,每个优先级值对应Thread类中的一个公共静态常量。

如果有多个线程在等待,并不是优先级越高就肯定越早执行,只是获得的机会更多一些,因此通常情况下,不要依靠线程优先级来控制线程的状态。



线程调度

1.      线程睡眠sleep()

                        i.              调用sleep()方法使线程处于睡眠,线程由运行状态进入不可运行的状态,睡眠时间过后线程再次进入可运行状态。

2.      暂停线程yield()

                        i.              调用yield()方法可暂停当前线程执行,将CPU资源让出来,允许其他线程执行。

                      ii.              Yield()的优点是保证有工作时不会让CPU闲置,主要用于编写多个合作线程,也适合于强制线程间的合作。

3.      连接线程join()

                        i.              调用join()方法可使当前线程暂停执行,等待调用该方法的线程的结束后再继续执行本线程。

4.      中断线程interrupt()

                        i.              Interrupt()方法可为线程设置一个中断标记,以便于run()方法运行时使用isInterrupted()方法能够检测到。此时,线程在sleep()之类的方法中被阻塞时,由sleep()方法抛出一个InterruptException()异常,然后捕捉这个异常以处理超时。

                      ii.              Interrupt()只是一个中断标记,并没有中断线程运行。



将线程标记为守护线程(后台线程):setDaemon(true); 注意该方法要在线程开启前使用。和前台线程一样开启,并抢资源运行,所不同的是,当前台线程都结束后,后台线程会自动结束。无论后台线程处于什么状态都会自动结束。


第二节总结

线程的同步

在多线程编程中,这种会被多个线程同时访问的资源叫做临界资源。



Synchronized关键字是一个修饰符,可以修饰方法或代码块。其作用是:对于同一个对象(不是一个类的不同对象),当多个线程都同时调用该方法或代码块时,必须一次执行,也就是说,如果两个或两个以上的线程同时执行该段代码,如果一个线程已经开始执行该段代码,则另外一个线程必须等待这个线程执行完这段代码才能开始执行。

多线程的同步提高了系统的安全问题



线程同步的两种表现形式:

1.同步代码块。



synchronzied(对象锁){

需要被同步的代码。(哪些需要同步哪些不需要一定要分清)

}



2.同步函数。



就是在函数上加了synchronzied关键字进行修饰。、

同步代码块可以使用任意对象作为锁。

同步函数使用的锁只有一个,就是this。

注意:static同步函数使用的锁是该函数所属类的对象。类名.class

售票系统中的线程同步方法:

package com.hbsi;

//模拟临界资源的类

class Tickets{

  publicinttickets;

  public Tickets(){

      tickets=10;

  }

  publicsynchronizedvoid action(String name){

      System.out.println(name+"抢到了第"+tickets+"号票");

      tickets--;

  }

}

//访问数据的线程

class TicketsThread extends Thread{

  Tickets t;

  String name;

  public TicketsThread(Tickets t,String name){

      this.t=t;

      this.name=name;

      start();

  }

  @Override

  publicvoid run() {

      try {

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

          t.action(name);

          Thread.sleep(20);

        }

      } catch (InterruptedException e) {

        // TODO Auto-generated catch block

        e.printStackTrace();

      }

  }



}

//测试多线程访问时的问题

publicclass TestMulThread2{

  publicstaticvoid main(String[] args) {

      // TODO Auto-generated method stub

      Tickets t=new Tickets();

      TicketsThread d1=new TicketsThread(t,"小王");

      TicketsThread d2=new TicketsThread(t,"小张");

  }

}

运行结果:

小王抢到了第10号票

小张抢到了第9号票

小王抢到了第8号票

小张抢到了第7号票

小王抢到了第6号票

小张抢到了第5号票

小王抢到了第4号票

小张抢到了第3号票

小王抢到了第2号票

小张抢到了第1号票



售票系统中的线程同步代码块:

package com.hbsi;





publicclass ticket1 implements Runnable{

  privateintticket=100;

  @Override

  publicvoid run() {

      // TODO Auto-generated method stub

      //Object obj=new Object();

      while(true){

        synchronized(this){

          if(ticket>0){

              try {

                Thread.sleep(100);

              } catch (InterruptedException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

              }

              System.out.println(Thread.currentThread().getName()+"..."+ticket--);

          }else{

              break;

          }

        }

      }

      

  }

  publicstaticvoid main(String[] args) {

      // TODO Auto-generated method stub

      ticket1 t=new ticket1();

      Thread td1=new Thread(t);

      Thread td2=new Thread(t);

      td1.start();

      td2.start();

  }

}



单例类懒汉式的线程同步:

Public class Single{

                  privatestatic Single s = null;

                  privateSingle(){}

                  publicstatic Single getInstance(){

                            if(s==null){

                                    synchronized(Single.class)

                                    {

                                              if(s==null)

                                                  s= new Single();

                                    }

                            }

                            return s;

                  }

        }

线程同步以后,懒汉式的安全性就进一步的提高。



线程的死锁:

产生死锁的原因主要是

因为系统资源不足。

进程运行推进的顺序不合适。

资源分配不当等。

如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。



产生死锁的四个必要条件

互斥条件:一个资源每次只能被一个进程使用。

请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。


第三节总结

线程间的通信
  两个或者两个以上的线程在处理同一个资源时,处理动作是不一样的。
  这时就需要将动作代码分别存放在不同的run方法,而run方法要封装单独的类中。
        示例:生产者,消费者。
-------------------------------------------------
        在同步中的使用的方法。
        wait,notify,notifyAll。这三个方式都定义Object类中。
        wait:让当前线程处于等待(冻结状态)状态。将该线程存入到了线程池中。
        notify:唤醒被等待的线程。通常唤醒的是线程池中的第一个。
        notifyAll:唤醒线程池中所有被等待线程。
        这些方法要用在同步中。并要明确三个方法所属的同步锁。
        synchronized(obj)
        {
                  obj.wait();
                  obj.notify()
        }
        在同步中无论被等待多少个线程,同时唤醒后,
        注意:只可能有一个线程会持有锁,并执行。其他线程即使子啊同步块中,也执行不了。
--------------------------------------------------- 
        wait(): 释放cpu的执行权。释放锁。
        sleep():释放cpu的执行权。不释放锁。


多线程在开发中的应用
1.下载
2.聊天

内部类中的多线程
public class ThreadDemo6 {

    /**
    * @param args
    */
    public static void main(String[] args) {
        
        new Thread(){
            public void run(){
                for(int i=0;i<100;i++){
                System.out.println("a="+i);
                }
            }
        }.start();
        
        for(int i=0;i<100;i++){
            System.out.println("b="+i);
        }
        
        Runnable r=new Runnable(){

            @Override
            public void run() {
                for(int i=0;i<100;i++){
                    System.out.println("c="+i);
                }
            }
            
        };
        new Thread(r).start();
    }
}

原创粉丝点击