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()      唤醒所有等待线程。

  • 相关阅读:
    SE Springer小组之《Spring音乐播放器》需求分析说明书一
    SE Springer小组之《Spring音乐播放器》可行性研究报告一、二(转载)
    SE Springer小组之《Spring音乐播放器》可行性研究报告五、六
    软件分析之QQ
    浅谈《软件工程》
    前端格式
    Django基础
    正则表达式
    任务-线程
    一名奔三的程序猿的困惑
  • 原文地址:https://www.cnblogs.com/chichung/p/10283654.html
Copyright © 2011-2022 走看看