内部类:
定义在类中的类,成为内部类。
好处是可以直接访问外部类中的成员(包括私有)。
外部类想访问内部类需要创建内部类对象。
匿名内部类:就是内部类的简化格式。
内部类必须继承一个类或者实现接口,这种情况下的内部类可以简化成匿名内部类。
格式: new 父类或者接口 () {定义子类的内容}
匿名内部类就是一个子类对象。
多线程
线程和进程:
进程:一个正在运行的程序就是一个进程。
线程:一个进程中有很多个线程。(每一个线程相当于一个执行的任务)
开启一个线程 相当于开启了一个CPU的执行路径(相对独立)。
CPU在执行多个线程的时候是随机的,跟线程的优先级有关。线程的调度采用分时调度,CPU会在多个线程中进行随机切换,优先级相同,时间片相同。
单线程程序:
特点:程序由上至下依次执行。(一个执行完,才会执行下一个)
好处:数据绝对安全,不牵扯到操作共享数据。
弊端:效率不高。
主线程
多线程的程序,除了主线程外,一般都叫子线程。
一个程序只有一个主线程。
main函数就是一个线程,并且是主线程。
主线程(main函数)是如何被执行的
JVM调用main函数 --> CPU为main函数开辟了一个执行路径 --> 相当于在这个执行路径中,执行main函数中的代码。
Thread线程类(开辟一个主线程以外的子线程)
1.创建Thread类的子类;
2.重写run方法(run方法中是线程要执行的代码);
3.调用start方法,开启线程(线程不能重复开启)。
线程的创建:
方式1:
class MyThread extends Thread{ public MyThread() { } public MyThread(String name) { super(name); } @Override public void run() { } }
继承Thread类,后在main函数中声明子类的对象。
方式2:使用接口的方式来创建
class RunnableImpl implements Runnable{ @Override public void run() { } } RunnableImpl runnableImpl = new RunnableImpl(); // 创建一个线程类对象 Thread thread = new Thread(runnableImpl); // 开启线程 thread.start();
方式3:用Thread的匿名内部类
Thread thread = new Thread() { public void run() { System.out.println("子线程执行的方法"); }; }; thread.start();方式4:用Runnable接口的匿名内部类
Runnable runnable = new Runnable() { @Override public void run() { System.out.println("接口实现类的方法"); } }; Thread thread2 = new Thread(runnable); thread2.start();线程名称的获取
在一般的线程中,名称可以通过get方法获取。但是主线程无法通过此方法获取,所以获取名称一般使用:
Thread.currentThread();方法,此方法可以获取当前正在执行的线程。
注意:由于Thread类中的set/get方法是由final修饰的,当想给Thread子类添加成员变量时,需注意提供set/get方法时,需要 改名。
创建了一个线程,相当于CPU开辟了一个独立的执行路径。相当于开辟了一个独立的方法栈来专门运行子线程中的方法。
线程在内存中的表现图:
线程状态(6种)