线程实现方式
一、并发和并行
**并发:**指两个或多个事物在同一时间段内发生。在一段时间内cpu在多个任务之间进行调度,交替执行。只不过切换时间很短,我们基本感觉不到。(一个人吃多个馒头)
**并行:**指两个或多个事物在同一时刻发生(同时)。多核心多线程CPU分别执行任务。(多人吃多个馒头)
并行速度比并发速度快。
二、进程和线程
所有应用程序都需要进入到内存中执行,零时存储RAM
**进程:**进入内存的程序叫做进程。
cpu也叫中央处理器,对数据进行计算,指挥电脑中软件和硬件干活。Core i5-2540m 是2核心4线程的cpu.4线程能够支持同时执行4个任务。
**线程:**点击功能执行,就会开启一条应用程序到cpu的执行路径,cpu就可以通过这个路径执行功能,这个路径就叫线程。
线程属于进程,是进程中的一个执行单元,负责程序的执行
例如:在一个应用程序中需要处理三个任务(视图刷新,数据计算,数据存储),单核心cpu处理时需要在任务之间进行快速切换。四核心八线程效率是其八倍,八个线程在任务之间进行高速切换。
三、线程调度和主线程
1.线程调度
分时调度:
抢占式调度:让优先级高的线程,谁使用cpu的时间就长。
2.主线程
执行主方法的线程就是主线程。如果不新建其它线程,java程序默认是单线程程序。执行从main方法开始,从上往下依次执行。
四、创建线程的方法
1.创建一个类继承Thread.
在子类中重写Thread类中的run方法。设置线程任务(开启线程要做什么)。创建子类对象。调用该对象strat方法,开启新线程,执行run方法。
public void start()使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
结果是两个线程并发地运行;当前线程(从调用返回给 start 方法)和另一个线程(创建的新线程。执行其 run 方法)。
多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
抛出:
IllegalThreadStateException - 如果线程已经启动。
java程序属于抢占式调度,那个线程的优先级高,那个线程优先执行;同一个优先级随机选择一个执行。
public class DemoThreqad {
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
for (int i =0 ;i<200;i++){
System.out.println("main"+i);
}
}
}
public class MyThread extends Thread{
@Override
public void run() {
for (int i =0 ;i<200;i++){
System.out.println("thread"+i);
}
}
}
2.实现Runnable接口
public interface **Runnable**Runnable //接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。
//1.创建Runnable实现类(只有run方法)
public class DemoRunnable implements Runnable{
//2.重写接口的run方法,设置线程任务
public void run(){
for(int i =0;i<20;i++){
System.out.println(Thread.currentThread().getName+i);
}
}
}
public class Demo{
public main(){
//3.创建实现类对象
DemoRunnalble run = new DemoRunnable();
//4.创建Thread类对象,构造方法中传递该实现类对象。
Thread t = new Thread(run);
//5.start
t.start();
//主线程
for(int i=0;i<20;i++){
System.out.println(Thread.currentThread().getName+i);
}
}
}
3.匿名内部类实现线程创建
匿名内部类:简化代码,把子类继承父类,重写父类的方法,创建子类对象合一步完成;把实现类实现接口,重写接口的方法,创建实现类对象合成一步完成;
new 父类/接口(){
重写父类/接口中的方法。
};
main(){
//继承
new Thread(){
public void run(){
for(int i=0;i<20;i++){
System.out.println(Thread.currentThread().getName+i+"extends");
}
}
}.start();
//接口
Runable r = new Runnable(){
public void run(){
for(int i=0;i<20;i++){
System.out.println(Thread.currentThread().getName+i+"interface");
}
}
};
new Thread(r).start();
//简化写法
new Thread(new Runnable(){
public void run(){
for(int i=0;i<20;i++){
System.out.println(Thread.currentThread().getName+i+"interface");
}
}
};).start();
}
五、多线程原理,随机性打印结果
六、多线程内存图解
七、Thread类的常用方法
1.获取线程的名字
public final String getName()//返回该线程的名称。 String name = getName();
public static Thread currentThread()//返回对当前正在执行的线程对象的引用。Thread t= Thread.currentThread(); Thread.currentThread().getName();
2.更改线程的名字
public final void setName(String name)改变线程名称,使之与参数 name 相同。
public Thread(String name)分配新的 Thread 对象。这种构造方法与 Thread(null, null, name) 具有相同的作用。
3.sleep方法
public static void sleep(long millis)
throws InterruptedException//在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。该线程不丢失任何监视器的所属权。
main(){
try{
Thread.sleep(1000);//睡眠一秒
sysout.println(i);
}
}
八、Thread和Runnable的区别
实现Runnable接口创建多线程好处:
- 避免了单继承的设计。
- 增强了程序的扩展性,降低了程序的耦合性。把设置线程任务和开启新线程进行了分离。实现类中重写run方法设置线程,在实现类对象中调用start开启新线程。