多线程
定义:多任务同时执行就是多线程,如果没有任务,就不需要使用多线程
线程和进程之间的区别:
进程:资源分配的最小单位
线程:cpu调度的最小单位
一个进程可以包含1~n个线程
线程开启的方式:
1.继承Thread类,重写run()方法 (重要)
创建子类对象,调用start()方法,开启多线程
2.实现Runnable接口,重写run()方法 **(重要)
3.实现Callable接口,重写call()方法 (了解)
方法1:
继承Thread类,重写run()方法 (重要)
创建子类对象,调用start()方法,开启多线程
1、public class ThreadDemo01 extends Thread{}
自定义类extends(继承)了Thread类;
2、@Override
public void run() {
for(int i=1;i<=100;i++){
System.out.println(" ");}}
重写Thread中的run()方法;
3、主程序启动线程
public static void main(String[] args) {
ThreadDemo01 th=new ThreadDemo01();
//void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
// th.start(); //开启线程
// th.run();
for(int i=1;i<=100;i++){
System.out.println(" ");
}
th.start(); //注意:不能把启动线程的程序放在后面,这样就会多次调用线程启动。
}
缺点:假如这个程序已经继承了其它的类,就不能再继承Thread类。
方法2:
实现Runnable接口,重写run()方法 **(重要)
开启线程: Thread类做代理,调用Thread类中的start方法开启线程
优点:
避免了单继承的局限性
实现资源共享
方法:
1、调用(implement ),Runnable接口;
public class ThreadDemo02 implements Runnable{
2、重写Runnable里面的run方法;
@Override
public void run() {
for(int i=1;i<=100;i++){
System.out.println(" ");
}
}
3、在主程序里面创建线程对象,实现了Runnable接口作为参数传入,简写:Thread t=new Thread(new ThreadDemo02());
public static void main(String[] args) {
ThreadDemo02 th=new ThreadDemo02();
Thread t=new Thread(th);
//void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
t.start(); //开启线程
for(int i=1;i<=100;i++){
System.out.println(" ");
}
}
}
线程状态
新生状态:new线程对象的时候,这个线程处于新生状态
就绪状态:调用start()方法,线程进入就绪状态,进入到就绪队列,进入就绪状态代表线程有能力执行,但是要等到cpu调用,分配时间片才能执行
运行状态:当前cpu调度,分配时间片给就绪状态的线程,当前线程执行
阻塞状态:sleep...
终止状态:结束
1.如果线程一旦进入到阻塞状态不会直接进入运行状态,阻塞状态解除要进入到就绪状态
2.线程一个旦结束,无法恢复,如果重新开启,也是一个新的线程
* 如何控制线程的终止:
1.调用stop(),destory(),已过时,不推荐
2.线程正常执行结束
3.添加标识控制
*
* 进入线程就绪状态的几种情况:
* 1.start()方法
* 2.yield 礼让线程
* 3.线程之前切换
* 4.解除阻塞状态,线程进入到就绪状态
*
* 进入线程阻塞状态的几种情况:
1.sleep方法
2.join方法
3.wait方法
4.IO操作
暂停线程执行的sleep()和yield()方法
Sleep()能够通过设置时间,让正在运行的线程进入阻塞状态,直到休眠时间满了,进入就绪状态;
Yield()让正在运行的线程直接进入就绪状态,让出CPU的使用权;
知识点:extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,JAVA中不支持多重继承,但是可以用接口来实现,extends只能继承一个类,implements可以实现多个接口。
方法:Thread.sleep(1000) 设置等待时间1000毫秒;
Thread.yield(); 可引起线程的切换
联合线程join()俗称插队
Join()方法的案例
Thread th =new Thread(new son());
th.start();
try {
th.join();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("儿子丢了");
}
System.out.println("喝茶");
如上th.join() 表示另外一个儿子的线程插队进来了,必须要一定要让儿子的行为结束才能执行父类的线程的最后一步。
线程的状态和优先级
查看线程的状态:
* Thread.State getState() 返回该线程的状态。
*
* 线程优先级:
* void setPriority(int newPriority) 更改线程的优先级。
* int getPriority() 返回线程的优先级
* 1~10表示 1是最小 10是最大 默认是5
* MIN_PRIORITY 最小
* NORM_PRIORITY 默认
* MAX_PRIORITY 最大
线程的常用方法:
isAlive() 判断线程是否还玩终止,也就是在运行中,或者;
getPriority() 取得线程的优先级数值
setPriority() 设置线程的优先级数值
setName() 给线程一个名字
getName() 取得线程的名字
currentThread() 取得当前正在运行的线程的对象
线程安全(线程同步等待机制)
多个线程同时操作同一份资源的时候,可能会发生线程不安全问题
* 控制线程安全:加锁 synchronized 同步
* 同步方法: 在方法上面加锁
* 同步静态方法
* 同步成员方法
* 同步块: synchronized(){}
* 锁this,锁资源,锁类
*
* 锁的必须是不变的内容
* 锁的范围太大,效率低,锁的范围太小,容易锁不住
*
*
* 单例:懒汉式是线程不安全的
线程同步
由于一个进程的多个线程共享同一块存储空间,为了避免同一个数据对象被多个线程访问造成问题。