zoukankan      html  css  js  c++  java
  • 多线程的应用

     

    一、进程和线程的概念

       每个程序运行至少需要一个进程,都有一个执行的路径,在这个进程中又至少有一个线程。我们在电脑上同时开启许多个程序一样,

    如果是单核cpu处理器的情况,那么同一时刻cpu只会调度一个线程,而我们视觉上感觉都在并发执行,那是因为cpu在完成快速的切换。

    在main函数中,进行着一个主线程,也就是一个程序至少有一个线程。

    二、线程的生命周期:

      1、创建线程对象

      2、调用start方法,进入就绪状态,等待cpu分配时间片

      3、运行状态:分配到时间片进入运行状态,这个时候线程既有运行资格,又有执行权。

      4、阻塞状态:线程进入阻塞

        调用sleep,线程放弃cpu执行权,等待时间到,进入就绪态

        调用yield,线程放弃当前cpu执行权,重新分配时间片

        调用wait,线程放弃cpu执行权,等待唤醒

        调用join,线程必须等待join的线程执行完,才能继续执行

      5、 结束状态,线程正常执行完任务结束

     

    三、创建线程的两种方法:

    1、通过继承Thread来创建线程:

      (1)、创建一个子类继承extends  Thread类

      (2)、在子类中重写run()方法。

      (3)、创建一个子类的对象,就是创建了一个线程

      (4)、调用start()方法,启动线程。

     

    2、通过实现Runnable接口来创建线程。

      (1)、创建一个子类来实现Runnable接口

      (2)、重写Runnable接口中的Run()方法

      (3)、在主函数中使用子类创建对象

      (4)、Thread 创建线程,然后把子类对象作为参数传进去。

     

    四、调用run方法和start方法的区别

      如果直接调用run()方法,那么和普通的函数调用没有任何区别,就是先去执行调用函数,然后再返回到主函数中来顺序执行,

    其实线程并没有被启动。而调用start()方法,进行了两个步骤,一是启动线程,二是调用run()方法,但是调用之后,线程并没有

    进入运行状态,而是出于就绪状态,它有运行资格,但是没有执行权,处于等待cpu分配资源的阶段。

    五、为什么要覆盖Thread或者接口中的run()方法

      因为run()方法能被线程所调用,所以run()方法中通常是我们要运行的代码,所以,我们在定义一个子类时,要把我们要线程来

    执行的程序代码放进去,所以要重写run()方法;

    六、同步代码块和同步函数

      1、同步代码块的应用,我们知道在多个线程同时操作一段代码时,如果执行到某一句代码时,cpu有可能切换到其他的线程,这样保留

    的数据就会改变,不能确保安全性,为了提高代码的安全性,我们要给特定的代码上锁以确定在某一个线程能够执行时,其他的线程进不去。

      格式如下:synchronized(对象){  

            执行代码; 

             }

      同步函数:public  synchronized  void   show(){        

             执行代码;

           }

      给函数或者代码块上锁确实能够提高安全性,但是也耗费了资源,因为线程每次执行都要进行判断,而且如果某线程在执行中睡眠或者

    异常,哪怕其他的线程抢到cpu 的执行权,也进不去。  

      2、同步函数中用的锁是this   ,静态同步方法使用锁是该方法所在类的字节码文件对象(类名、class)。

           

    七、实现方法和继承方法的区别

      实现方法可以避免单继承的局限性,比如Student类它继承了Person这个类,而它里面需要多线程来完成的代码时,那么它是不能够再去

    继承Thread类,所以接口Runnable解决了这个问题。

      1、获取线程名称的方法:Thread.currentThread(),获取当前线程的名称

      2、设置线程名称有两种方式:一是:通过构造函数初始化,然后在super()调用父类的方法;

      二是:通过父类Thread中的方法setName()来完成。

    下面通过代码来体现上面的一些概念:

    案例一:

     1 public class ThreadDemo {
     2     public static void main(String[] args){
     3         Athread a1=new Athread("线程一");
     4         Athread a2=new Athread("线程二");
     5         //a1.setName("线程一");
     6         //a2.setName("线程二");
     7         a1.start();
     8         a2.start();
     9         for(int x=0;x<60;x++)
    10         {
    11             System.out.println("Hello,World!");
    12         }
    13     }
    14 }
    15 
    16 //创建一个类继承Thread线程类
    17 class Athread extends Thread {
    18     Athread(String name)
    19     {
    20         super(name);
    21     }
    22     public void run()//重写Thread中run()方法
    23     {
    24         for(int i=0;i<60;i++)
    25         {
    26             System.out.println(Thread.currentThread()+"xiancheng"+i);
    27         }
    28     }
    29 }


    案例二:卖票程序

     1 public class TicketDemo {
     2     public static void main(String[] args) {
     3         Ticket t = new Ticket();
     4         Thread t1 = new Thread(t);
     5         Thread t2 = new Thread(t);
     6         Thread t3 = new Thread(t);
     7         Thread t4 = new Thread(t);
     8         //设置线程名称
     9         t1.setName("线程一");
    10         t2.setName("线程二");
    11         t3.setName("线程三");
    12         t4.setName("线程四");
    13         //启动线程
    14         t1.start();
    15         t2.start();
    16         t3.start();
    17         t4.start();
    18     }
    19 }
    20 
    21 class Ticket implements Runnable {
    22     int ticket = 100;
    23     Object obj = new Object();
    24 
    25     public void run() {
    26         while (true) {
    27             synchronized (obj)//同步代码块,进行上锁
    28             {
    29                 if (ticket > 0) {
    30                     try {
    31                         Thread.sleep(10);
    32                     } catch (Exception e) {
    33                     }
    34                     System.out.println("正在卖第" + ticket-- + "张票");
    35                 }
    36             }
    37         }
    38     }
    39 }


    案例三:银行存钱系统

     1 public class BankDemo {
     2     public static void main(String[] args) {
     3         Bank b = new Bank();
     4         Thread t1 = new Thread(b);
     5         Thread t2 = new Thread(b);
     6         t1.setName("储户A");
     7         t2.setName("储户B");
     8         t1.start();
     9         t2.start();
    10     }
    11 }
    12 
    13 //创建一个类,实现Runnable接口
    14 class Bank implements Runnable {
    15     Deposit d = new Deposit();
    16 
    17     public void run() {
    18         for (int i = 0; i < 3; i++) {
    19             d.add();
    20         }
    21     }
    22 }
    23 
    24 //定义一个存钱的类
    25 class Deposit {
    26     int sum = 0;
    27     Object obj = new Object();
    28 
    29     public void add() {
    30         synchronized (obj) {
    31             sum += 100;
    32             System.out.println(Thread.currentThread() + "sum=" + sum);
    33         }
    34     }
    35 }


     

  • 相关阅读:
    P1162 填涂颜色
    P1238 走迷宫
    U68364 _GC滑迷宫
    P4783 【模板】矩阵求逆
    P2613 有理数取余
    koa1链接mongodb
    koa的跨域访问
    mongodb 降序
    mongodb 分页(limit)
    mongodb 查询数据
  • 原文地址:https://www.cnblogs.com/warrior4236/p/6055729.html
Copyright © 2011-2022 走看看