并发与并行:
并发:多个任务交替执行 (一个人吃两个馒头,两个交替啃)
并行:同时执行。(n个人吃n个馒头) 速度快些。
线程与进程:
进程:进入到内存中的程序叫进程。
线程:
主线程:
执行主方法(main)的线程
单线程程序:Java程序中只有一个线程,从main方法开始,从上到下依次执行。
JVM执行main方法,main方法会进入栈内存,
然后JVM找到操作系统开辟一条main方法通向cpu的执行路径,
cpu就可以通过这个路径执行main方法,这个路径叫main(主)线程。
多线程:
java程序属于抢占式调度,哪个线程高,哪个线程就优先执行,同一级别随机执行。
创建多线程程序的第一种方式:
java.lang.Thread 类:是描述线程的类,想实现多线程程序,就必须继承该类。
实现步骤:
1、创建Thread类的子类。
2、子类重写run方法, 来设置线程任务。
3、创建子类对象,调用start()方法,开启新的线程,执行run方法。
结果是:两个线程并发执行。
public class MyThread extends Thread { @Override public void run() { for (int i=0;i<3;i++){ System.out.println("run->"+i); } } }
public class ThreadDemo { public static void main(String[] args) { MyThread myThread=new MyThread(); myThread.start(); for (int i=0;i<3;i++){ System.out.println("main->"+i); }
main->0
run->0
main->1
run->1
main->2
run->2 } }
多线程运行原理:
new MyThread的时候,又开辟了一条通向cpu的新路径,来执行run方法。
此时,对cpu而言,就有了两条执行路径。
main线程和新线程一起抢夺cpu的执行权。
多线程内存分析:
开始执行程序时,开辟一块栈内存,main方法入栈。
此时,如果直接调用run方法的话,也是在这块栈内存执行run(),也就是仍然
是main线程程序(单线程)程序。
而如果调用的是start(),会另外开辟一块栈空间,run()入栈执行。
Thread类的常用方法:
获取线程名称:
1、Thread类的方法,getName();
2、获取当前正在执行的线程 static Thread currentThead(),然后用getName();
第一种:
public class MyThread extends Thread { @Override public void run() { System.out.println(getName()); } }
public static void main(String[] args) { new MyThread().start(); new MyThread().start(); //Thread-0 // Thread-1 }
第二种:
public static void main(String[] args) { System.out.println(Thread.currentThread().getName()); //main } }
设置线程名称:
1、void setName(String name) 2、设置带参构造函数
sleep方法:
public static void sleep(Long ...) :使当前正在执行的线程以指定毫秒暂停。
public static void main(String[] args) { for (int i=0;i<5;i++){ System.out.println(i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
创建多线程程序的第二种方式:
实现Runnable接口:
java.lang.Runnable. 实现类必须定义run的无参方法。
java.lang.Thread 类的构造方法:
1、Thread(Runnable target) 分配新的Thread对象。
2、Thread(Runnable target,String name)。
实现步骤:
1、创建Runnable接口的实现类。
2、重写run方法,设置线程任务。
3、创建实现类的对象,用含有Runnable接口的构造函数创建Thread类对象。
4、用start方法,开启新线程执行run();
public class RunnableClass implements Runnable { @Override public void run() { for (int i=0;i<5;i++){ System.out.println( Thread.currentThread().getName() +"->"+i ); } } }
public static void main(String[] args) { RunnableClass runnable=new RunnableClass(); Thread thread=new Thread(runnable); thread.start(); for (int i=0;i<5;i++){ System.out.println( Thread.currentThread().getName() +"->"+i ); } }
两种实现多线程方法的区别:
实现Runnable接口实现多线程的好处:
1、避免单继承的局限性:
继承了Thread类就不能继承其他类了,而使用接口的方式还可以继承其他类。
2、增强程序的扩展性,降低了程序的耦合性(解耦):
用实现Runnable接口的方式,把设置线程任务和开启线程进行分离(解耦 )
匿名内部类实现多线程:
作用:
简化代码,把实现类实现接口,重写方法,创建实现类方法统一完成。
格式: new 父类/接口(){重写方法};
public static void main(String[] args) { new Thread() { @Override public void run() { for (int i=0;i<5;i++){ System.out.println(currentThread().getName()); } } }.start(); new Thread(new Runnable() { @Override public void run() { for (int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()); } } }).start(); }