zoukankan      html  css  js  c++  java
  • java实现多线程的两种方式

    1.继承Thread类

    public class Demo1 {
        public static void main(String[] args) {
            MyThread mt = new MyThread();
            mt.start();
    
            for (int i = 0 ; i < 1000 ; i++){
                System.out.println("bbb");
            }
        }
    }
    
    class MyThread extends Thread{
        @Override
        public void run() {
            for (int i = 0 ; i < 1000 ; i++){
                System.out.println("aaaaa");
            }
        }
    }

    2.实现Runnable接口

    原理:Thread构造函数中传入了Runnable的引用,成员变量记住了它,调用start()方法时调用了run()方法,判断成员变量Runnable的引用是否为空。不为空时执行。编译时看的是Runnable的run(),运行是执行的是子类的run方法。

    public class Demo2 {
        public static void main(String[] args) {
            Thread t = new Thread(new MyThread2());    // 父类引用指向子类对象
            t.start();
    
            for (int i = 0 ; i < 1000 ; i++){
                System.out.println("bbb");
            }
        }
    }
    
    class MyThread2 implements Runnable{
    
        @Override
        public void run() {
            for (int i = 0 ; i < 1000 ; i++){
                System.out.println("aaaaa");
            }
        }
    }

    3.两种方式的优缺点以及使用场景

    • 继承Thread

    优点:可以直接使用Thread类中的方法,代码简单

    缺点:如果已经有了父类,就不能用这种方法了。

    • 实现Runnable接口

    优点:即使自定义的线程有了父类也没有关系,因为有了父类也可以实现接口,而且接口是可以多实现的

    缺点:不能直接使用Thread中的方法,需要先获取到线程对象后,才能得到Thread的方法,使用起来比较麻烦

    • 建议:

    如果没有父类,用Thread,否则用Runnable。

    4.用匿名内部类的方式实现上面两种方式

    public class Demo3 {
        public static void main(String[] args) {
            new Thread() {                                   // 继承Thread类
                @Override
                public void run() {
                    for (int i = 0 ; i < 1000 ; i++){
                        System.out.println("aaaaa");
                    }
                }
            }.start();
    
    
            new Thread(new Runnable() {                      // 将Runnable的子类对象传递给Thread的构造方法
                @Override
                public void run() {
                    for (int i = 0 ; i < 1000 ; i++){
                        System.out.println("bbb");
                    }
                }
            }).start();
        }
    }

     

    5.给线程设置名称以及获取线程名称

    public class Demo3 {
        public static void main(String[] args) {
            // 继承Thread的第一种方法
            new Thread("a线程") {
                @Override
                public void run() {
                    for (int i = 0 ; i < 1000 ; i++){
                        System.out.println(this.getName() + "---aaaaa");
                    }
                }
            }.start();
    
            // 继承Thread的第二种方法
            new Thread() {
                @Override
                public void run() {
                    this.setName("c线程");
                    for (int i = 0 ; i < 1000 ; i++){
                        System.out.println(this.getName() + "---ccc");
                    }
                }
            }.start();
    
            // 实现Runnable接口的方法(利用Thread的currentThread静态方法获取当前进程)
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0 ; i < 1000 ; i++){
                        Thread.currentThread().setName("b线程");
                        System.out.println(Thread.currentThread().getName() + "---bb");
                    }
                }
            }).start();
        }
    }

    6.多线程常用的一些方法

    static void        sleep(long millis)    使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。

    void    setDaemon(boolean on)    将此线程标记为 daemon线程或用户线程。

    static void    yield()    对调度程序的一个暗示,即当前线程愿意让生当前使用的处理器。

    void    setPriority(int newPriority)    更改此线程的优先级。

     除了Thread类的方法,还会结合Object类的某些方法使用:

    void    notify()    唤醒正在等待对象监视器的单个线程。

    void    notifyAll()     唤醒正在等待对象监视器的所有线程。

    void    wait()    导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。

    几个面试问题:

    1.在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法。

    2.为什么wait方法和notify方法定义在Object类中?

    因为锁对象可以使任意对向,Object是所有类的基类,所以wait方法和notify方法需要定义在Object这个类中。

    3.sleep方法和wait方法的区别?

    sleep方法必须传入参数,参数就是时间,时间到了自动醒来。

    wait方法可以传参数也可以不传参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待

    sleep方法在同步函数或同步代码块中,不释放锁

    wait方法在同步函数或同步代码块中,释放锁

    7.互斥锁(ReentrantLock类)

    JDK1.5以后的,可以替代wait和notify。

    void    lock()     获得锁。

    void    unlock()      尝试释放此锁。

    Condition    newCondition()      返回Condition用于这种用途实例Lock实例。

          Condition的方法:

                   void    await()     导致当前线程等到发信号或 interrupted 。

                   void    signal()    唤醒一个等待线程。

                   void    signalAll()      唤醒所有等待线程。

  • 相关阅读:
    人工智能背后的故事
    idea 开发插件。
    安卓工作室 Android studio 或 Intellij IDEA 美化 修改 汉化 酷炫 装逼 Android studio or Intellij IDEA beautify modify Chinesization cool decoration
    安卓工作室 android studio文件和代码模板,以及汉化出错问题
    安卓工作室 android studio 汉化后,报错。 设置界面打不开。Can't find resource for bundle java.util.PropertyResourceBundle, key emmet.bem.class.name.element.separator.label
    android studio的汉化 教程 及解析
    安卓工作室Android Studio 快捷键
    安卓工作室 android studio 的 汉化 美化 定制 Android studio's Chinesization beautification customization
    VR开发 VR development
    Lakeshore 中文开发界面,示例项目,飞机大战 等 Lakeshore Chinese development interface, sample project, aircraft war, etc
  • 原文地址:https://www.cnblogs.com/chichung/p/10283654.html
Copyright © 2011-2022 走看看