一、多线程原理:
程序启动运行main时候,java虚拟机启动一个进程,主线程main在main()调用时候被创建。随着调用mt的对象的start方法,另外一个新的线程也启动了,这样,整个应用就在多线程下运行。多线程执行时,在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间。进行方法的压栈和弹栈。当执行线程的任务结束了,线程自动在栈内存中释放了。但是当所有的执行线程都结束了,那么进程就结束了。
线程状态图
二、线程的创建方法:
1. 创建Thread类的子类:
(1)创建Thread类的子类;
(2)在Thread子类中重写run方法,设置线程任务;
(3) 创建Thread子类的实例,即创建了线程对象;
(4)调用子类对象的start()方法来启动该线程。(start方法执行,会开拍新的栈空间以执行run方法体)
测试类:
public class Demo01 {
public static void main(String[] args) {
//创建自定义线程对象
MyThread mt = new MyThread("新的线程!");
//开启新线程
mt.start();
//在主方法中执行for循环
for (int i = 0; i < 10; i++) {
System.out.println("main线程!"+i);
}
}
}
自定义Thread子类:
public class MyThread extends Thread {
//定义指定线程名称的构造方法
public MyThread(String name) {
//调用父类的String参数的构造方法,指定线程的名称
super(name);
}
/**
* 重写run方法,完成该线程执行的逻辑
*/
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName()+":正在执行!"+i);
}
}
}
2. 实现Runable接口:
(1)创建Runable接口的实现类;
(2)在实现类中重写Runable接口的run方法,设置线程任务;
(3)创建Runable接口实现类对象;
(4)创建Thread对象,构造方法传递Runable接口实现类对象;
(5)调用Thread类的start()方法,启动新线程执行run方法。
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
public class Demo {
public static void main(String[] args) {
//创建自定义类对象 线程任务对象
MyRunnable mr = new MyRunnable();
//创建线程对象
Thread t = new Thread(mr, "小强");
t.start();
for (int i = 0; i < 20; i++) {
System.out.println("旺财 " + i);
}
}
}
3. 匿名内部类实现线程创建:
public class NoNameInnerClassThread {
public static void main(String[] args) {
Runnable r = new Runnable(){
public void run(){
for (int i = 0; i < 20; i++) {
System.out.println("张宇:"+i);
}
}
};
new Thread(r).start();
for (int i = 0; i < 20; i++) {
System.out.println("费玉清:"+i);
}
}
}
new Thread(){
@Override
public void run(){ ... }
}.start();
new Thread(new Runable(){
@Override
public void run(){ ... }
}).start();
使用Runable接口创建线程的好处:
- 适合多个相同的程序代码的线程去共享同一个资源。
- 可以避免java中的单继承的局限性。
- 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
- 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。