学习多线程,创建多线程的三种方式_实现多线程的三种方法,2024年最新binder机制面试题

59 阅读5分钟

}



public class Demo01Thread { public static void main(String[] args) { //3.创建Thread类的子类对象 MyThread mt = new MyThread(); //mt.run(); 不会开启新线程 mt.start(); //main线程会继续执行for循环 for (int i = 0; i < 20; i++) { System.out.println("main-->"+i); }

}

}


新的线程和main线程优先级相同,cpu会随机执行某一个线程,就会出现随机性打印结果



run-->0 main-->0 main-->1 run-->1 main-->2 run-->2 main-->3 run-->3 main-->4 run-->4 run-->5 run-->6 run-->7 run-->8 run-->9 main-->5 run-->10 main-->6 run-->11 main-->7 run-->12 main-->8 run-->13 main-->9 run-->14 main-->10 run-->15 main-->11 main-->12 main-->13 main-->14 main-->15 main-->16 main-->17 run-->16 main-->18 run-->17 run-->18 run-->19 main-->19


**随机性打印结果原理:**  
 1:JVM首先运行main方法,找到操作系统开辟一条通向cpu的路径,这个路径就是主线程,cpu通过这个路径就可以执行main  
 2:执行MyThread mt = new MyThread();,开辟一条新的通向cpu的路径。mt.start();用来执行run方法  
 3:现在有两条路径通向cpu,对于cpu而言就有了选择的权力,可以随机选择一个来执行(主线程和新线程的优先级相同),所以就有了随机性打印结果。  
 4:内存图解  
 ![在这里插入图片描述](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/1ac615ebc64e4fd88227512262fdbcbb~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771252652&x-signature=MwzBiREwwYj193YXl4%2FYkACDv1Q%3D)  
 **获取线程的名称**


主线程:main  
 新线程:Thread-0,Thread-1…Thread-n


使用Thread类中的getName方法  
 String getName() 返回此线程的名称。



public class MyThread extends Thread{ @Override public void run() { //1.使用Thread类中的getName方法 String name = getName(); System.out.println(name); } }



public class Demo01Thread { public static void main(String[] args) { //线程1 MyThread myThread = new MyThread(); myThread.start();//Thread-0 //线程2 new MyThread().start();//Thread-1 } }


可以先获取当前正在执行的线程,再通过getName获取线程名称  
 static Thread currentThread() 返回对当前正在执行的线程对象的引用。



public class MyThread extends Thread{ @Override public void run() { //2.可以先获取当前正在执行的线程,再通过getName获取线程名称 Thread currentThread = Thread.currentThread(); String name = currentThread.getName(); System.out.println(name); } }



public class Demo01Thread { public static void main(String[] args) { //线程1 MyThread myThread = new MyThread(); myThread.start();//Thread-0 //线程2 new MyThread().start();//Thread-1

    //获取主线程名称
    System.out.println(Thread.currentThread().getName());
}

}


**设置线程的名称**


可以使用Thread的方法**setName**  
 void setName​(String name) 将此线程的名称更改为等于参数 name 。



public class MyThread extends Thread{ @Override public void run() { System.out.println(Thread.currentThread().getName()); } }



public class Demo01 { public static void main(String[] args) { MyThread mt = new MyThread(); mt.setName("aaa"); mt.start(); } }


添加一个带参构造方法,参数传递线程的名称,调用父类的带参构造,把名字传递给父类



public class MyThread extends Thread{ public MyThread() { }

public MyThread(String name) {
    super(name);
}

@Override
public void run() {
    System.out.println(Thread.currentThread().getName());
}

}



public class Demo01 { public static void main(String[] args) { MyThread mt2 = new MyThread("bbb"); mt2.start();//bbb } }


**Thread类中的sleep方法**  
 static void sleep​(long millis) 导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序的精度和准确性。  
 **示例:制作秒表**



public class Demo01 { public static void main(String[] args) { //秒表 for (int i = 0; i < 60; i++) { System.out.println(i); //让程序睡眠1s 1s=1000ms try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } } } }


**创建多线程程序的第二种方式:实现Runnable接口**  
 java.lang.Runnable  
 **Runnable接口应由任何其实例由线程执行的类实现。 该类必须定义一个名为run的无参数的方法。**


java.lang.Thread类的构造方法:


Thread​(Runnable target) 分配新的 Thread对象。  
 Thread​(Runnable target, String name) 分配新的 Thread对象。  
 **实现步骤**:


1:创建一个类实现Runnable接口  
 2:重写Runnable接口中的run方法,设置线程任务  
 3:创建Runnable接口的实现类对象  
 4:创建Thread类对象,构造方法中传递Runnable接口的实现类对象  
 5:调用Thread类中的start方法,开启新线程,执行run方法



//1.创建一个类实现Runnable接口 public class RunnableImpl implements Runnable { //2.重写Runnable接口中的run方法,设置线程任务 @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+"-->"+i); } } }



public class Demo01 { public static void main(String[] args) { //3.创建Runnable接口的实现类对象 RunnableImpl r = new RunnableImpl(); //4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象 Thread t = new Thread(r); //5.调用Thread类中的start方法,开启新线程,执行run方法 t.start();

    for (int i = 0; i < 20; i++) {
        System.out.println(Thread.currentThread().getName()+"-->"+i);
    }
}

}


**实现Runnable接口的方式和继承Thread类方式不同**


1:避免单继承的局限性  
 一个类继承了Thread类,就不能继承其他类  
 一个类实现了Runnable接口,还可以继承别的类,实现其他接口  
 2:增强了程序的扩展性  
 实现Runnable接口,把设置线程任务(重写run方法目的就是设置线程任务  
 和开启线程)和创建Thread对象(调用Start方法开启线程)  
 进行了解耦,分离


### 创建多线程程序的第三种方式:匿名内部类


匿名内部类作用:简化代码


把子类继承父类,重写父类方法,创建子类对象,合成一步完成  
 把实现类继承实现接口,重写接口的方法,创建实现类对象,合成一步完成  
 **匿名内部类的方式实现多线程程序的三种方式:**  
 父类Thread,new MyThread().start();



public class Demo01 { public static void main(String[] args) { //父类Thread //new MyThread().start();

    new Thread() {
        //重写run方法,设置线程任务
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                System.out.println(Thread.currentThread().getName()+"-->"+i);
            }
        }
    }.start();
}

}


**接口Runnable,new Thread(new RunnableImpl()).start() ;**



public class Demo02 { public static void main(String[] args) { //接口Runnable //new Thread(new RunnableImpl()).start() ;

    new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {

img img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!