美文网首页程序员Java基础
再学—Java基础:多线程(1)

再学—Java基础:多线程(1)

作者: 0ur | 来源:发表于2019-01-22 00:04 被阅读5次

    进程与线程:

    • 什么是进程:就是应用程序在运行时期,所占用的内存空间区域。

    一个程序也可以说是一个进程,开辟的内存可能不是连续的0-88,99-120的内存块,这样的话可能就造成了其他程序和当前的程序的数据错乱,还有一些什神奇的错误,这时候伟大的工程师,采用了虚拟内存,就是虚拟出来连续的内存,指向非连续的内存这地址)

    • 什么是线程:是进程中的单个顺序控制流,是一条执行路径。

    单线程:一个进程只有一个可执行的路径
    多线程:一个进程有多个可执行的路径

    线程的实现方式

    线程是依托于进程而存在的,而进程是系统创建出去的,java并不能操作系统,但是可以调C/C++,实现创建进程,从而可以实现线程。(线程进程都是由操作系统,依靠JVM找操作系统,才能实现线程的功能)

    • Thread类:继承
        public class MyThread extends Thread {
            @Override
            public void run() {
                super.run();
                //线程一般执行的是耗时任务  尤其是在android 端
                for (int i = 0; i < 100; i++) {
                    System.out.println(i);
                }
            }
        }
    
        //开启线程
        public class ThreadDemo {
    
           public static void main(String[] args) {
               MyThread myThread = new MyThread();
               myThread.start();
        }
    
    }
    
    • Runnable :实现
    public class RunnableDemo implements Runnable {
     
    
        @Override
        public void run() {
            //线程一般执行的是耗时任务  尤其是在android 端
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
            }
        }
    }
    //开启线程
    public class ThreadDemo {
    
        public static void main(String[] args) {
            RunnableDemo  runnableDemo  = new RunnableDemo ();
           //Theand的构造方法 可以出入一个runnable对象
            new Thread(runnableDemo ).start();
        }
    
    }
    
    

    两种方式对比:实现接口,避免单继承局限性

    这样我们就开启了两个线程,
    那么,我们在继承Thread类或实现Runnable类之后,为什么要重写run()方法呢?
    因为不是类中的所有代码都需要被线程执行的(个人理解继承Thread或实现Runnable的子类,不一定全是要 执行在run()方法里,可能存在其他的自定义方法,和成员变量)。而这个时候,为了区分哪些代码能够被线程执行,java提供了Thread类中的run()用来包含那些被线程执行的代码。

    • 设置和获取线程的名字
      Thread类的基本获取和设置方法
      public final String getName():获取线程的名称。
      public final void setName(String name):设置线程的名称
    public class ThreadDemo {
    
        public static void main(String[] args) {
            RunnableDemo runnableDemo = new RunnableDemo();
            Thread thread = new Thread(runnableDemo);
            thread.setName("001");
            System.out.println(thread.getName());
            thread.start();
    
            MyThread myThread = new MyThread();
            myThread.setName("002");
            System.out.println(myThread.getName());
            myThread.start();
            //获取当前正在执行的线程名字
            System.out.println(Thread.currentThread().getName());
        }
    
    }
    
    
    • 线程的操作
      public static void sleep(long millis):线程休眠
    public class MyThread extends Thread {
        @Override
        public void run() {
            super.run();
            //线程一般执行的是耗时任务  尤其是在android 端
            try {
                //当前线程被执行的时候,会每次睡眠一秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
            }
        }
    }
    

    public final void wait() :线程等待

    public class MyThread extends Thread {
        @Override
        public void run() {
            super.run();
            //线程一般执行的是耗时任务  尤其是在android 端
            synchronized (this) {
                try {
                    //次线程就会被挂起,放弃CPU的执行权和释放锁,等待notify()
                    wait();
    //            wait(1000);
    //            wait(2000, 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < 100; i++) {
                System.out.println(i);
            }
        }
    }
    

    sleep()和wait()的区别:
    使用上
    从使用角度看,sleep是Thread线程类的静态方法,而wait是Object顶级类的费静态方法()。
    sleep可以在任何地方使用(指的是当前执行的线程休眠),而wait只能在同步方法或者同步块中使用
    CPU及资源锁释放
    sleep,wait调用后都会暂停当前线程并让出cpu的执行时间,但不同的是sleep不会释放当前持有的对象的锁资源,到时间后会继续执行,而wait会放弃所有锁并需要notify/notifyAll后重新获取到对象锁资源后才能继续执行。
    异常捕获
    sleep需要捕获或者抛出异常,而wait/notify/notifyAll不需要。

    为什么线程方法等待,唤醒写了Object类?
    notify 等待,唤醒本锁上的线程,必须有锁的支持,锁是任意对象,将wait,notify方法写了Object类,保证任意对象锁都可以调用线程,等待唤醒方法

    public final void stop():中断线程

    public class StopThreadDemo {
    
        public static void main(String[] args) {
            Thread t = new Thread(new StopThread());
            t.start();
            t.stop();
    
        }
    }
    
    class  StopThread implements Runnable {
    
        @Override
        public void run() {
            while (true) {
                System.out.println("run.........");
            }
        }
    }
    

    线程无任何输出,直接停止了,不再继续执行了

    public void interrupt():中断线程

    public class InterruptThreadDemo {
    
        public static void main(String[] args) {
            InterruptThread t = new InterruptThread();
            t.start();
            try {
                //如果5秒 不醒来 我就弄死你
                Thread.sleep(5000);
                t.interrupt();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    
    class InterruptThread extends Thread {
    
        @Override
        public void run() {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                System.out.println("线程被终止了");
            }
            System.out.println("run.........");
        }
    
    
    }
    

    但是interrupt()方法执行后,它会终止线程的状态,还会继续执行run方法里面的代码。

    线程的终止 1 stop 过时 2,interrupt 3,标记执行循环,run方法结束

    public final void join():线程加入

    public class JoinThread {
        public static void main(String[] String) {
            JoinRunnable joinRunnable1 = new JoinRunnable();
            JoinRunnable joinRunnable2 = new JoinRunnable();
            JoinRunnable joinRunnable3 = new JoinRunnable();
    
            Thread t1=new Thread(joinRunnable1);
            t1.setName("我是 1");
            Thread t2=new Thread(joinRunnable2);
            t2.setName("我是 2");
            Thread t3=new Thread(joinRunnable3);
            t3.setName("我是 3");
    
            t1.start();
            try {
                t1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            t2.start();
            t3.start();
        }
    
    
    }
    
    class JoinRunnable implements Runnable {
    
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName().toString());
            }
        }
    }
    

    等待该线程终止,使用了join方法的线程,会一直运行结束,其他线程抢CPU的资源

    public static void yield():线程礼让

    /**
     * 线程的让步 yield
     */
    public class YieldThreadDemo {
    
        public static void main(String[] args) {
    
            YieldRunnable yieldRunnable = new YieldRunnable();
            Thread t0 = new Thread(yieldRunnable);
            Thread t1 = new Thread(yieldRunnable);
            t0.start();
            t1.start();
        }
    }
    
    class YieldRunnable implements Runnable {
    
        @Override
        public void run() {
            for (int x = 0; x < 100; x++) {
                Thread.yield();
                System.out.println(Thread.currentThread().getName() + "....run");
            }
        }
    }
    

    这个方法暂停当前正在执行的线程对象,并执行其他线程,出现互相谦让的状态。
    让多个线程的执行更和谐,但是不能靠它保证一人一次。

    public final void setDaemon(boolean on):守护线程

    /**
    * setDaemon(true)   守护线程
    */
    public class DaemomThreadDemo {
    
       public static void main(String[] args) {
    
           Thread t0 = new Thread(new DaemomRunnable());
    
           t0.setDaemon(true);//线程t0 是 main线程的守护线程,如果main执行完或者main线程终止,main的守护线程都死亡
    
           t0.start();
       }
    
    
    }
    
    class DaemomRunnable implements Runnable {
    
       @Override
       public void run() {
           for (int i = 30; i > 0; i++) {
               System.out.println("run........");
           }
       }
    }
    

    当线程设为A线程的守护线程,A死亡后,所有的守护线程都死亡

    线程的运行状态图

    Thread.png

    第一次画图,见笑了,😄😄😄

    • 模拟火车站卖票,引出多线程的数据安全问题
    public class ThreadDemo {
    
        public static void main(String[] args) {
            RunnableDemo runnableDemo1 = new RunnableDemo();
            RunnableDemo runnableDemo2 = new RunnableDemo();
            RunnableDemo runnableDemo3 = new RunnableDemo();
    
            new Thread(runnableDemo1).start();
            new Thread(runnableDemo2).start();
            new Thread(runnableDemo3).start();
        }
    
    }
    
    public class RunnableDemo1 implements Runnable {
        //定义一百张车票
        private int mTicket = 100;
    
        @Override
        public void run() {
            while (mTicket > 0) {
                //每出售一张 --操作
                System.out.println(Thread.currentThread().getName() + " 出售车票= " + mTicket-- + " 张");
            }
        }
    }
    
    
    
    data.jpg

    多线程状态下,数据出现了问题,怎么解决多线程下的数据安全问题,请看下节

    如有出入,往大佬扶正,谢谢!!!!

    相关文章

      网友评论

        本文标题:再学—Java基础:多线程(1)

        本文链接:https://www.haomeiwen.com/subject/weckhqtx.html