1.线程和进程
进程:一个正在运行的程序就是进程
线程:一个进程中有很多线程
每一个线程相当于一个执行的任务
开启一个线程相当于开启了一个cpu的执行路径
CPU在执行多个线程的时候是随机的,跟线程的优先级有关
分时调度 CPU会在多个线程中随机切换
标准的单线程程序
特点:程序忧伤至下依次执行(一个执行完才执行下一个)
好处:绝对安全 不牵扯到操作共享数据
弊端:效率不高
public static void main(String[] args) {
add();
delete();
System.out.println("执行完");
}
public static void add() {
for (int i = 0; i < 100; i++) {
System.out.println("add---"+i);
}
}
public static void delete() {
for (int i = 0; i < 100; i++) {
System.out.println("delete---"+i);
}
}
2.主线程
多线程的程序除了主线程外 一般都叫子线程
一个程序只有一个主线程
main函数就是一个线程 是主线程
主线程(叫main的函数)是如何执行的
jvm调用main函数-->cpu就为叫main的函数开辟一个执行路径-->相当于在这个执行路径中执行main函数的代码
Thread线程类(开辟一个主线程以外的线程 子线程)
1.创建一个thread类的子类
2.重写run方法 run方法就是你要线程执行的代码
3.调用start方法 开启线程 (不能重复开启)
子线程默认名字 thread-0
class SubThread extends Thread{
@Override
public void run() {
}
}
创建一个子线程
开启多个线程时 多个线程会同时执行 并且相对独立的执行单元
主线程出现异常 不影响子线程
SubThread subThread=new SubThread();
subThread.start();
SubThread subThread1=new SubThread();
subThread1.start();
3.线程的名字
public static void main(String[] args) {
NameThread nameThread=new NameThread("haha");
//设置线程名字
// nameThread.setName("线程---1");
System.out.println(nameThread.getName());
//获取主线程的名字
Thread currentThread= Thread.currentThread();
System.out.println(currentThread.getName());
}
}
class NameThread extends Thread{
//构造方法
public NameThread() {
}
public NameThread(String name) {
//调用父类的构造方法
super(name);
}
@Override
public void run() {
//获取的是子线程的对象
Thread currentThread = Thread.currentThread();
System.out.println("我是子线程"+currentThread.getName());
//简写:
//System.out.println(Thread.currentThread().getName());
//获取线程的名字
System.out.println(getName());
}
创建一个线程类 提供又参无参 set/get方法
class MyThread extends Thread{
//定义了自己的name属性
private String name;
public MyThread() {
}
//有参
//1.给父类name赋值
//2.给本类的name赋值
public MyThread(String name,String myname) {
super(name);
this.name=myname;
}
//set/get 父类中使用final修饰了该方法 不能被子类重写
//修改方法名
public void setMyName(String name) {
this.name=name;
}
public String getMyName() {
return this.name;
}
@Override
public void run() {
}
创建一个线程 相当于 cpu开启一个独立执行路径
相当于开辟一个独立的方法栈 专门运行子线程的方法
4.线程的创建方式2
使用接口实现类的方法来创建
public static void main(String[] args) {
RunnableImpl runnableImpl=new RunnableImpl();
Thread thread=new Thread(runnableImpl);
thread.start();
}
}
class RunnableImpl implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
}
5.匿名内部类的方法创建线程
匿名内部类创建出来的对象是该类的子类对象
new Test() {}; 相当于test的子类对象
并且可以在后面的大括号例重写父类中的方法
public static void main(String[] args) {
}
Test test=new Test() {
@Override
public void fun() {
System.out.println("我是匿名内部中重写的fun方法");
}
};
test.fun();
}
class Test{
public void fun() {
System.out.println("我是test中的fun方法");
}
直接创建接口类的实现类对象
注意:这种方法new后面跟的是父类名
但是创建出来的对象 确实子类或实现类的对象
public static void main(String[] args) {
TestInter testInter=new TestInter() {
@Override
public void fun() {
System.out.println("我是实现类的fun方法");
}
};
testInter.fun();
}
interface TestInter{
public abstract void fun();
}
利用匿名内部类方式
给集合中3个学生对象 按年龄进行排序(比较器)
public static void main(String[] args) {
Comparator<Student> comparator=new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
};
TreeSet<Student>set=new TreeSet<>(comparator);
set.add(new Student("aa", 16));
set.add(new Student("aa", 18));
set.add(new Student("aa", 6));
System.out.println(set);
}
上面代码一起写
TreeSet<Student>set2=new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
});
1(thread子类的方式)
Thread thread=new Thread() {
@Override
public void run() {
System.out.println("子线程执行的方法");
}
};
thread.start();
2(接口实现类的方式)
Runnable runnable=new Runnable() {
@Override
public void run() {
System.out.println("子线程方法");
}
};
Thread thread3=new Thread(runnable);
thread3.start();
3方式2的两步写一起
Thread thread2=new Thread(new Runnable() {
@Override
public void run() {
System.out.println("子线程方法");
}
});
thread2.start();
6.线程状态(6种)
新建状态(new Thread())
运行状态(start())
死亡状态(run方法运行完毕)
受阻塞状态(cpu为执行该线程时)
休眠状态(sleep方法 休眠时间过了 恢复)
等待状态(wait notify)
线程调用start()方法就一定会变成运行状态吗?
不一定,调用start方法是表示该方法被cpu执行,但是cpu不一定运行,所以不一定变成运行状态,等待cpu的执行.这种状态叫受阻塞状态
主线程休眠:
参数时休眠时间单位毫秒
卡主主线程一秒
休眠时间结束会自动醒来
Thread.sleep(1000);
父类中的run方法没抛异常,子类只能try-catch处理
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}