• JAVA入门到精通-第40讲-线程


     把思想转换成程序。
     
     线程对象只能启动一个线程;
     导入导出项目:
    1,copy
     
    2,装到磁盘
    3,导入:import---General---Existing Project into Workspace
     4,浏览Brose-Copy project into workspace
      把项目拷贝到Eclipse中,
      不选的话,直接操作;
    -----------------------------------------
     这是可以的;

     
     这会报错,一个线程类只会启动一次;

     
      数据的并发;

     //售票窗口类
     
    //定义三个售票窗口
      
     //控制出票速度:
     Thread.sleep(100);
     
     各卖各的票没有共享;
    //看哪个线程在卖票
      
     Thread.currentThread().getName() 
    得到当前线程的名字;
     
    //线程共享所有的票
    (1)改成静态的;
    (2)用一个窗口,启动三次;
     
     这个数据应该是被共享的;

    同一张票被多个线程卖出,没有规律;并发造成的;

     
     a线程执行完1以后没有来得及执行第2句话,b线程进入;

     
     
     
       synchronized(Object);
       Object称为对象锁;Object类比门;
       线程排队-线程等待池-blocked
       直到对象锁被打开;
     
      
     同步代码块; this 就是对象锁,代表对象本身;
     
     
     有对象锁,线程的并发已经被控制住,会按照顺序卖;
     ---------------------------
     对象锁有0和1标志位,默认1,门打开,进入代码块使用;
     在进入的时候,会把标志位,变为0,门被锁上;
     
     如果1进入,1会被放到等待池里排队;
     如果2进入,2会先看等待池,有,在等待池排队;

     0号执行完,离开,把标志位重置为1,否则,会死锁:
     
    死锁:线程互读,并且并发;
     ------------------------------------------
     
     线程--区别
     线程--继承Thread VS 实现Runnable的区别
        从java的设计来看,通过继承Thread或者实现Runnable接口来创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口,如果一定要说它们有什么区别,总结几点:
    1、尽可能使用实现Runnable接口的方式来创建线程
    2、在使用Thread的时候只需要new一个实例出来,调用start()方法即可以启动一个线程,如:    Thread test=new Thread();
            test.start();
    3、在使用Runnable的时候需要先new一个实现Runnable的实例,之后用Thread调用,如:
        Test implements Runnable
        Test t=new Test();
        Thread test=new Thread(t);
        tset.start();

    线程--深入理解
    线程对象只能启动一个线程,见[Thread04.java]
    xxxxxxxxxx
    31
     
    1
    /**
    2
     * 功能:使用线程的注意事项
    3
     * 不论继承Thread或实现Rnunable接口都不能使用start启同一个线程2次
    4
     */
    5
    public class Thread04 {
    6
        public static void main(String[] args) {
    7
            Cat cat1=new Cat();
    8
            cat1.start();
    9
            //cat1.start();同一个线程,不能启动2次
    10
            
    11
            Dog dog1=new Dog();
    12
            Thread t=new Thread(dog1);
    13
            t.start();
    14
            //t.start();同一个线程,不能启动2次
    15
        }
    16
    }
    17
    18
    //猫类
    19
    class Cat extends Thread{
    20
        public void run(){
    21
            System.out.println("11");
    22
        }
    23
    }
    24
    25
    //狗类
    26
    class Dog implements Runnable{
    27
        public void run(){
    28
            System.out.println("2");
    29
        }
    30
    }
    31
     
    --------------------------------------------------------- 
    结论:不管是通过继承Thread,还是通过实现Runnable接口创建线程,它们的一个对象只能启动(即:start())一次。否则就会有异常抛出。

    两种创建线程的方法的区别
    创建线程有两种方法:1、继承Thread;2、实现Runnable接口;
    这两种方法有什么区别?
    用实现Runnable接口的特点
    1、用实现Runnable接口的方法创建对象可以避免java单继承机制带来的局限;
    2、用实现Runnable接口的方法,可以实现多个线程共享同一段代码(数据);
    因此建议大家如果你的程序有同步逻辑需求,则使用Runnable的方法来创建线程。

    java线程的同步--提出问题
    多线程的并发,给我们编程带来很多好处,完成更多更有效率的程序。但是也给我们带来线程安全问题。

    java线程的同步--解决问题
    解决问题的关键就是要保证容易出问题的代码的原子性,所谓原子性就是指:当a线程在执行某段代码的时候,别的线程必须等到a线程执行完后,它才能执行这段代码。也就是排队一个一个解决。
    java处理线程两步的方法非常简单,只需要在需要同步的代码段,用:
        synchronized(Object){你要同步的代码}
    即可。

     售票案例演示[Thread05.java]
     
    1
    /**
    2
     * 功能:使用线程的注意事项
    3
     * 线程并发同步锁synchronized(Object){}的使用
    4
     */
    5
    public class Thread05 {
    6
        public static void main(String[] args) {
    7
            //定义一个售票窗口
    8
            TicketWindow tw1=new TicketWindow();
    9
            
    10
            //使用三个线程同时启动
    11
            Thread t1=new Thread(tw1);
    12
            Thread t2=new Thread(tw1);
    13
            Thread t3=new Thread(tw1);
    14
            
    15
            t1.start();
    16
            t2.start();
    17
            t3.start();
    18
        }
    19
    }
    20
    21
    //售票窗口类
    22
    class TicketWindow implements Runnable {
    23
        //共有2000张票
    24
        private int nums=2000;
    25
        private Dog myDog=new Dog();
    26
    27
        public void run() {
    28
            while(true){
    29
                //出票速度是1秒出一张
    30
                try {
    31
                    Thread.sleep(1000);
    32
                } catch (Exception e) {
    33
                    e.printStackTrace();
    34
                }
    35
    36
                //认为if else要保证其原子性
    37
                //先判断是否还有票
    38
                synchronized(myDog){//synchronized(this){}为同步代码块
    39
                    if(nums>0){
    40
                        //显示售票信息
    41
                        //Thread.currentThread().getName()得到当前线程的名字
    42
                        System.out.println(Thread.currentThread().getName()+"正在售出第"+nums+"张票");
    43
                        nums--;
    44
                    }else{
    45
                        //售票结束
    46
                        break;
    47
                    }
    48
                }
    49
            }
    50
        }
    51
    }
    52
    53
    class Dog{
    54
    }
    55
     
    ------------------------------------
    java线程的同步--解决问题
    对同步机制的解释:
    java任意类型的对象都有一个标志位,该标志位具有0、1两种状态,其开始状态为1,当某个线程执行了synchronized(Object)语句后,object对象的标志位变为0的状态,直到执行完整个synchronized语句中的代码块后,该对象的标志位又回到1状态。
        当一个线程执行到synchronized(Object)语句的时候,先检查Object对象的标志位,如果为0状态,表明已经有另外的线程正在执行synchronized包括的代码,那么这个线程将暂时阻塞,让出CPU资源,直到另外的线程执行完相关的同步代码,并将Object对象的标志位变为状态,这个线程的阻塞就被取消,线程能继续运行,该线程又将Object的标志位变为0状态,防止其它的线程再进入相关的同步代码块中。
    如果有多个线程因等待同一个对象的标志位面而处于阻塞状态时,当该对象的标志位恢复到1状态时,只会有一个线程能够进入同步代码执行,其它的线程仍处于阻塞的状态。
    特别说明:
    1、上面所说的标志位用术语讲就是对象锁,文件锁。数据库会有行锁、表锁等
    2、synchronized(object)//object(就是对象锁)可以是任意类型对象

      
     

     




  • 相关阅读:
    ubuntu12.04.2上利用cmake安装opencv2.4.6
    微软无线鼠标3500滚轮问题
    Linux 安装 Tomcat
    Linux 安装 MySQL
    Linux 安装 JDK
    Linux 安装 Redis 及踩坑
    IDEA Git 撤销push(回退到指定版本)
    【Java】Ajax实现级联城市
    node.js更换镜像源
    【Java】数据库连接池的简单使用
  • 原文地址:https://www.cnblogs.com/xuxaut-558/p/10045751.html
Copyright © 2020-2023  润新知