进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。
程序:指令序列,用来让cpu完成指定的任务,一个.java程序经过编译形成.class文件,操作系统创建一个JVM虚拟机进程(每执行一次main方法就创建一个JVM进程),并在虚拟机中加载class文件并运行,进程通过创建你新线程来执行具体的任务。
线程:线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
使用jdk中的命令分析线程信息
Thread.java类的8个构造方法
构造函数Thread(Runnable target) 不仅可以传入Runnable接口对象,而且可以传入一个Thread类的对象。
在run()方法前添加synchronized关键字,一个线程调用run方法前会判断run方法有没有上锁,如果run方法被上锁,说明其他线程正在调用,必须等待。
synchronized可以对任意对象及方法加锁,被加锁的这段代码称为“互斥区”或“临界区”。
返回代码正在被哪个线程调用
run2的构造函数是被main线程调用,run方法是被Thread-0的线程调用
执行方法run()和start()方法的区别:
isAlive方法判断当前线程是否存活
在指定的时间(毫秒)内让当前正在执行的线程休眠,这个当前正在执行的线程是指this.currentThread()返回的线程。
在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠
作用是返回一个表示该线程堆栈跟踪元素数组
将当前线程的堆栈跟踪信息输出到标准错误流
用于取得线程的唯一标识
调用interrupt方法仅仅在当前线程中做了一个停止的标记,并不是真正的停止线程
public class MyThread5 extends Thread { @Override public void run() { super.run(); try{ for (int i = 0; i <500000 ; i++) { if(this.isInterrupted()){ System.out.println("已经是停止状态,我要推出了!"); throw new InterruptedException(); //或者不抛异常,直接return } System.out.println("i="+(i+1)); } } catch (InterruptedException e){ System.out.println("进入run方法中的catch了!!"); e.printStackTrace(); } } public static void main(String[] args) { try{ MyThread5 myThread5 = new MyThread5(); myThread5.start(); Thread.sleep(2000); myThread5.interrupt(); } catch (InterruptedException e) { System.out.println("main catch!!"); e.printStackTrace(); } System.out.println("end!!!"); } }
sleep和interrupt
不管调用顺序,只要interrupt()和sleep()方法碰到一起就会出现异常:在sleep状态执行interrupt()方法会出现异常;调用interrupt()方法给线程打上了中断标记,在执行sleep()方法也会出现异常
public class MyThread6 extends Thread { private int i=0; @Override public void run() { super.run(); try { while (true){ i++; System.out.println("i="+i); Thread.sleep(1000); } } catch (InterruptedException e){ e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { MyThread6 myThread6 = new MyThread6(); myThread6.start(); Thread.sleep(8000); myThread6.stop(); } }
在Java多线程中,可以使用suspend()方法暂停线程,使用resume()方法来恢复线程的执行
suspend()、resume() 方法是过期作废的方法,原因是容易造成公共同步对象被独占,其他线程无法访问公共同步对象的结果,因此想要实现对线程进行暂停与恢复的处理,可以使用wait()、notify()或者notifyAll()方法
System.out.println也是同步方法
yield方法的作用是放弃当前的cpu资源,让其他任务去占用cpu执行时间,放弃的时间不确定,有可能刚刚放弃,马上又获得cpu时间片
在Java中线程的优先级分为1-10共10个等级,如果线程优先级小于1或者大于10,则JDK抛出异常 throw new IllegalArguementException()
public class MyThread10 extends Thread { @Override public void run() { super.run(); System.out.println("MyThread10 run priority="+this.getPriority()); } } public class MyThread9 extends Thread { @Override public void run() { super.run(); System.out.println("MyThread9 run priority="+this.getPriority()); MyThread10 myThread10 = new MyThread10(); myThread10.start(); } public static void main(String[] args) { System.out.println("main thread begin priority="+Thread.currentThread().getPriority()); //Thread.currentThread().setPriority(6); System.out.println("main thread end priority="+Thread.currentThread().getPriority()); MyThread9 myThread9 = new MyThread9(); myThread9.start(); } }
去掉注释
2. 优先级的规律
高优先级的线程总是大部分先执行完,但不代表高优先级的线程全部先执行完,CPU尽量将执行资源让给优先级比较高的线程,线程的优先级与执行顺序具有不确定性、随机性
Java中有两种线程,一种是用户线程,另一种是守护线程
守护线程是一种特殊线程,当进程中不存在用户线程了,则守护线程自动销毁,典型的守护线程是垃圾回收线程
只用当最后一个用户线程结束时,则守护线程才随着JVM一同结束,守护线程的作用是为其他运行的线程提供服务。
public class MyThread11 extends Thread { private int i=0; @Override public void run() { super.run(); try{ while(true){ i++; System.out.println("i="+(i+1)); Thread.sleep(1000); } } catch (InterruptedException e){ e.printStackTrace(); } } public static void main(String[] args) { try{ MyThread11 myThread11 = new MyThread11(); myThread11.setDaemon(true); myThread11.start(); Thread.sleep(5000); System.out.println("main 结束,守护线程也随之结束!"); } catch (InterruptedException e){ e.printStackTrace(); } } }