多线程

*多线程:多任务同时执行 ,如果需要多线程才使用,不需要无需使用

* 优点:提高效率,完善功能

*     缺点:开发复杂,可能出现不安全情况

* 线程 和 进程的区别

*     1.每个进程都有自己独立的代码和数据空间,内存空间

*     2.一类线程共享进程的资源

*     3.一个进程包含一到多个线程

*     4.进程是资源分配的最小单位

*     5.线程是cpu调度的最小单位

*

* 多线程的创建方式:

*     1.继承Thread类,重写run()方法  + start()开启多线程

*  2.实现Runnable接口,重写run()方法  --推荐

*      1)避免单继承的局限性

*      2)实现资源共享

*  3.实现 Callable接口,重写call方法

*      1)使用麻烦

*      2)抛出异常,具有返回值

public class ThreadDemo01 extends Thread {

    /*

     * 定义要执行的线程体

     */

    @Override

    public void run() {

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

            System.out.println("一边陪女朋友...");

        }

    }

    public static void main(String[] args) {

        ThreadDemo01 th=new ThreadDemo01();  //创建多线程

        th.start();  //开启多线程  等待cpu分配时间片,调用线程的执行

        //th.run(); //单线程,方法的调用,执行完毕run()方法,才能继续执行main方法的代码

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

            System.out.println("一边敲代码.....");

        }

        //th.start();   是多线程的开启,但是没有切换执行费的效果

    }

}

2.实现Runnable接口,重写run()方法  --推荐

*      1)避免单继承的局限性

*      2)实现资源共享

重写方法异常问题:

     *  如果父类方法没有抛出异常,子类重写方法就不能抛出异常

     *  如果父类方法有抛出异常,子类方法抛出异常<=父类

使用内部类,匿名内部类,Lambda表达式的形式开启线程

public class ThreadDemo06 {

    //静态内部类

    static class Inner1 extends Thread{

         @Override

         public void run() {

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

                 System.out.println("hahahha"+i);

             }

         }

    }

    

    public static void main(String[] args) {

         //局部内部类

         class Inner2 extends Thread{

             @Override

             public void run() {

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

                     try {

                          Thread.sleep(20);

                     } catch (Exception e) {

                          // TODO Auto-generated  catch block

                          e.printStackTrace();

                     }

                     System.out.println("heheheh"+i);

                 }

             }

         }

         //静态内部类

         new Inner1().start();

         new Inner2().start();

         

         //匿名内部类

         new Thread(new Runnable(){

             @Override

             public void run() {

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

                     try {

                          Thread.sleep(20);

                     } catch (Exception e) {

                          // TODO Auto-generated  catch block

                          e.printStackTrace();

                     }

                     System.out.println("heiheihei"+i);

                 }

             }

             

         }).start();

         //Lambda表达式

         new Thread(()->{

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

                 try {

                     Thread.sleep(20);

                 } catch (Exception e) {

                     // TODO Auto-generated catch  block

                     e.printStackTrace();

                 }

                 System.out.println("xixixixi"+i);

             }

         }).start();

    }

}

线程的状态

 *  新生 :new Thread(),创建一个线程

 *  就绪 :start(),就绪不是运行,就绪状态的线程会处于就绪队列中,等待cpu的调度

 *  运行 :当cpu为某个现成饭非配时间片,这个线程开始执行

 *  阻塞 :sleep(),阻止线程的正常执行,等待阻塞解除

 *  终止 :线程结束

 *  注意:

 *   1.如果一个线程一旦终止,没有办法恢复,就算重新开启也不是原来的线程

 *   2.阻塞状态接触,没有办法直接恢复运行状态,都会进入就绪状态

 *  如何使线程进入到终止状态:

 *   1.执行执行完毕  2.通过外部干涉   1)调用stop() destroy()  2)通过外部标识判断**

 *  如何使线程进入到就绪状态:

 *   1.start()

 *   2.阻塞状态接触直接进入就绪状态

 *   3.yield() 礼让线程

 *   4.线程切换,被切换的线程直接进入就绪状态

 *  如何使线程进入到阻塞状态:

 *   1.sleep()

 *   2.join() 插队

 *   3.wait()

 *   4.IO操作

*sleep(毫秒数) 线程睡眠,静态方法

 *   可以方法问题发生的可能性

 *   模拟网络延时

 *  使程序进入阻塞状态,让出cpu的资源,如果遇到对象锁的情况,sleep()抱着对象资源睡觉,不会释放对象的锁

 */ yield() 礼让线程  高风亮节  静态方法

 *  可以放大对方执行的可能性

join()合并线程   插队线程

 * 爸爸让儿子去买烟...

线程的状态getState() 返回枚举类型的状态信息

 * 优先级:  提高|降低可能性,不能去决定性作用

 *  1~10之间的数字表示线程的优先级  1最小 10最大       默认是5

 *  staticintMAX_PRIORITY

                      线程可以具有的最高优先级。

    staticintMIN_PRIORITY

              线程可以具有的最低优先级。

    staticintNORM_PRIORITY

              分配给线程的默认优先级。

 * setPriority()设置线程的优先级别

 * getPriority()获取线程的优先级别

线程安全问题:

 *  多个线程,同时操作同一个资源的时候,有可能出现线程不安全的问题

 * synchronized 同步锁

 *  同步方法 :方法上添加synchronized

 *       成员方法

 *       静态方法:锁静态方法相当于锁类

 *  同步块:

 *       synchronized(this|类名.class|资源){...}

 *       this:对象

 *       类名.class:类

 *       资源:成员变量

 * 注意:

 *  锁的范围太大,效率低,锁的范围太小,锁不住

 *  锁一定要锁不变的内容,变的锁不住,自定义的引用数据类型的对象地址

 * 

 *  单例模式

 *   懒汉式:线程不安全的

 *  双重检查:double check :提高效率,把锁的范围控制在相对来说最小

/*

*  12306案例 线程不安全问题处理1:

*       锁方法范围太大,效率太低,但是较简单

*/

public class Web12306_02 implements Runnable{

    //共享的资源 100张票

    int tickets=100;

    

    // A B C

    @Override

    public void run() {

         //循环买票

         while(true){

             if(test()){

                 break;

             }

         }

    }

    

    //定义一个方法,每次循环要执行的代码

    //返回值: true,没票了结束购买  false->继续购买

    public synchronized boolean test(){

         if(tickets<=0){

             return true;

         }

         try {

             Thread.sleep(200);

         } catch (InterruptedException e) {

         } //执行到这个方法,就休息200ms

         System.out.println(Thread.currentThread().getName()+"正在买"+tickets--+"张票");

         return false;

    }

    

    

    public static void main(String[] args) {

         Web12306_02 web=new Web12306_02(); //资源---每一个线程执行的线程体都是Web12306_03类中的代码run

         //创建线程

         new Thread(web,"武国伟").start();  

         new Thread(web,"魏中华").start();

         new Thread(web,"李啸").start();

    }

    

}

12306案例 线程不安全问题处理2:

*  锁块:锁资源:一般指成员属性

*       资源只能是引用数据类型

*       一定要锁不变的内容

*       

*/

public class Web12306_03 implements Runnable{

    //共享的资源 100张票

    Ticket tickets=new Ticket();  //一个对象中100张票

    @Override

    public void run() {

         //循环买票

         while(true){

             synchronized (tickets) {  //锁的对象的地址

                 if(tickets.num<=0){

                     break;

                 }

                 try {

                     Thread.sleep(200);

                 } catch (InterruptedException e)  {} //执行到这个方法,就休息200ms

                 System.out.println(Thread.currentThread().getName()+"正在买"+tickets.num--+"张票");

             }

         }

    }


    public static void main(String[] args) {

         Web12306_03 web=new Web12306_03(); //资源---每一个线程执行的线程体都是Web12306_03类中的代码run

         //创建线程

         new Thread(web,"武国伟").start();  

         new Thread(web,"魏中华").start();

         new Thread(web,"李啸").start();

    }


}

class Ticket{

    int num=100;

}

* 12306案例 线程不安全问题处理2:

*  锁块: this:所对象-->指代当前调用成员方法的对象

*             如果对象中存在多个资源,相当于把一整个对象的所有资源全部锁住了

*           如果只需要锁对象中的某个资源,提高效率,可以只锁资源

*/

public class Web12306_04 implements Runnable{

    //共享的资源 100张票

    int tickets=100;

    @Override

    public void run() {

         //循环买票

         while(true){

//           synchronized (this) {  //同步快中的代码执行完毕才会释放对象锁

                 if(tickets<=0){

                     break;

                 }

                 try {

                     Thread.sleep(200);

                 } catch (InterruptedException e)  {} //执行到这个方法,就休息200ms

                 System.out.println(Thread.currentThread().getName()+"正在买"+tickets--+"张票");

//           }

         }

    }


    public static void main(String[] args) {

         Web12306_04 web=new Web12306_04(); //资源---每一个线程执行的线程体都是Web12306_03类中的代码run

         //创建线程

         new Thread(web,"武国伟").start();  

         new Thread(web,"魏中华").start();

         new Thread(web,"李啸").start();

    }


}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 3,001评论 1 18
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 2,515评论 1 15
  • 在java中对于多线程的实现一定要有一个多线程的主类,多线程主类的实现是要有一定要求的 继承Thread父类 在j...
    渔樵店阅读 314评论 0 0
  • 进程是指运行中的应用程序,每一个进程都有自己独立的内存空间,对一个应用程序可以同事启动多个进程。例如,对于I...
    99度蓝99阅读 217评论 0 0
  • 7月20日知识点 今天的主要内容——线程 线程线程的基本概念线程与进程的区别线程的两种创建方式(掌握)注意线程两种...
    须臾之北阅读 13,738评论 0 4