1. 线程创建的两种方法
- 方法一:
- 将类声明为Thread的子类
- 定义Thread类的子类,并重写该类的run()方法,该run()方法中的方法体代表了线程需要完成的任务,因此把run()方法称为线程执行体
- 创建Thread子类的实例,即创建了线程对象
- 调用线程对象的start()方法来启动该线程
- SubThread.java
1.定义一个子线程的类,继承Thread类;
public class SubThread extends Thread {
/*
*2.在子线程类中重写run方法,在run方法中打印子线程的名称;
*/
public void run() {
// 打印子线程的名称
System.out.println("subThread:" + Thread.currentThread().getName());
}
}
- ThreadDemo.java
public class ThreadDemo {
public static void main(String[] args) {
// 4.在main方法中打印主线程的名称;
System.out.println("main:" + Thread.currentThread().getName());
// 5.在main方法中创建子线程对象;
SubThread st = new SubThread();
// 6.调用子线程对象的start方法,开启子线程。
st.start();
}
}
- 方法二:
- 声明一个类实现Runnable 接口
- 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体
- 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,Thread对象才是真正的线程对象
- 调用线程对象的start()方法来启动线程
RunableImpl.java
//定义一个子任务类,实现Runnable接口
public class RunableImpl implements Runnable {
@Override
public void run() {
//在子任务类中重写run方法,在run方法中打印子线程的名称
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-子线程" + i);
}
}
}
demo2Runalbe.java
//定义一个测试类
public class demo2Runable {
public static void main(String[] args) {
//创建一个子任务对象
RunableImpl run = new RunableImpl();
//创建一个Thread类的对象,并把子任务对象作为参数传递给Thread类的构造方法
Thread t = new Thread(run);
//调用Thread类的start()方法开启线程
t.start();
//主线程中打印线程名称
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "-主线程" + i);
}
}
}
2. 线程中的run方法与start方法区别
- 线程对象调用run()方法不开启线程,仅是对象调用方法。线程对象调用start()方法开启线程,并让jvm调用run()方法在开启的线程中执行。
3. 实现Runnable接口的优势
- 适合多个相同的程序代码的线程去共享同一个资源。
- 可以避免java中的单继承的局限性。
- 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和数据独立。
- 线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类。
4. 线程状态
- NEW(新建) 线程刚被创建,但是并未启动。
- Runnable(可运行)
线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。
- Blocked(锁阻塞)
当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。
- Waiting(无限等待)
一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。
- Timed Waiting(计时等待)
同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。
- Teminated(被终止)
因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。
5. 匿名内部类创建线程
格式:
new 父类/接口(){
重复父类/接口中的方法
};
- 匿名内部类作用:简化代码
- 把子类继承父类,重写父类的方法,创建子类对象合一步完成
- 把实现实现类接口,重写接口中的方法,创建实现类对象合成一步完成
匿名内部类的最终输出:子类/实现类对象,而这个类没有名字
- 方法一:
public class InnerRunable {
public static void main(String[] args) {
/*
线程实现的第一种方法。继承Thread类,生成子类对象,重写run()方法。调用start()启动线程。
new Thread(){ }
大括号内重写run()方法
返回匿名的Thread子类对象。
*/
new Thread(){
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "--> override1---" + i);
}
}
}.start();
}
}
/*
Runnabel run = new RunableImpl();//多态
Thread t = new Thread(run);
t.start()
*/
Runnable r = new Runnable(){
//重写run方法,设置线程任务
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "--> override2---" + i);
}
}
};
new Thread(r).start();
//简化接口的方式
new Thread(new Runnable(){
//重写run方法,设置线程任务
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "--> override3---" + i);
}
}
}).start();
IDEA快捷键
- alt+enter 导入包,自动修正代码
- ctr+y 删除光标当前行
- ctr+d 复制光标当前行到下一行
- ctr+alt+L 格式化代码
- ctr+/ 单选注释
- ctr+shift+/ 多行注释,再次按的话则取消注释
- alt+ins 自动生成代码,toString,set,get
- alt+shift+上下箭头 移动当前行
- 在IDEA工具中, Ctrl+空格 的快捷键,可以帮助我们补全代码,但是这个快捷键和Windows中的输入法切换快捷 键冲突,需要修改IDEA中的快捷键。
- File->Settings->keymap->Main menu->code->Completion->Basic
- 双击 Basic->remove->Ctrl+空格