}
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:内存图解

**获取线程的名称**
主线程: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++) {
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!