多线程
线程就是进程中一个负责程序执行的控制单元(执行路径),一个进程中可以有多个执行路径,称为多线程
jvm启动时就启动了多个线程,例如:
- 执行main函数的线程
- 负责垃圾回收的线程
所有线程都结束后,jvm才结束运作。当程序出现下图所示情况时,主线程中d1先调用show函数,循环完成后d2才能调用show,这时候想要d1,d2同时运行,则需要新建一个线程。
创建多线程
方法一:
- 将类声明为Thread的子类,该子类应重写Thread 的run方法,接下来可以分配并启动该子类的实例。
tip:
- Thread类用于描述线程,run方法就是封装自定义线程运行任务的函数,run方法中就是任务代码
。 - 调用start方法开启线程
- 可以通过Thread的getName()获取线程的名称,命名方式为:Thread-编号(编号从0开始编)
- 使用currentThread()返回对当前正在执行的线程对象的引用
- 主线程的名字的main
- 可以将线程重新命名,直接用super()继承
class Demo extends Thread
{
private String name;
Demo(String name)
{
this.name = name;
//super(name);改变线程的名称
}
public void run()
{
for(int x=0; x<10; x++)
{
for(int y=0; y<99999999; y++) {}
System.out.println(name+'...x='+x+'...name='+Thread.currentThread().getName());
}
}
}
class DemoThread
{
main()
{
Demo d1 = new Demo('小刘');
Demo d2 = new Demo('X');
//d1.run();d2.run();测试run和start的区别
d1.start();//线程1
d2.start();//线程2
System.out.println('over...'+Thread.currentThread().getName());
}
}//CPU在主线程和两个新建的线程之间不断切换
方法二:
- 定义类实现Runnable接口
- 覆盖接口中的run方法,将线程的任务代码封装到run方法中
- 通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread的构造函数的参数进行传递
- 调用线程对象的start方法开启线程
class Demo implements Runnable
{
public void run()
{
show();
}
public void show()
{
for(int x=0; x<10; x++)
{
System.out.println('x='+x+'...name='+Thread.currentThread().getName());
}
}
}
class ThreadDemo
{
main(){
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t2.start();
}
}
两种方法的区别:
- 方法一是将原来的类变成Thread的子类,然后继承Thread的所有方法,方法二只是将线程的任务进行了对象的封装,避免了java单继承的局限性。
内存
线程1调用的方法进线程1的栈,哪个线程出现异常哪个线程就会结束,其余线程正常进行。
线程的状态
如下图所示,线程一开启就开启了执行资格,但被CPU切换到的才具备执行权,即同一时刻只有一个线程具有执行权,其余的线程都是临时阻塞状态。