“并行”和“并发”的区别在于,“并行”是多个进程同时执行。而“并发”表面上看是多个线程同时执 行,而实际上是多个线程在轮换执行,也就是说某一时刻只有一个线程在运行。但是由于处理器的运行速度非常之快,所以给人的感觉是多个线程在同时运行。
线程/进程开销资源线程小共享所在进程中的资源进程大彼此间资源独立就是在多cpu的情况下。 当在单cpu时,多线程只能起到同时处理多个任务的作用,而并不会提高运行速度。
如果在单线程的情况下,就等同于用同一台电话拨打100次通话。那么这时候如果该线路出现问题,后面的人都无法得到通知。 如果是多线程的情况下,如果某一个线路出现了阻塞,并不影响其他线路工作。
运行结果 Thread-1号生产线完成了一量火箭的组装! Thread-0号生产线完成了一量火箭的组装!
//通过继承Thread public class RocketFactory2 extends Thread { @Override public void run() { super.run(); System.out.println(Thread.currentThread().getName() + "号生产线完成了一量火箭的组装!"); } public static void main(String[] args) { new RocketFactory2().start(); new RocketFactory2().start(); } } 运行结果 Thread-1号生产线完成了一量火箭的组装! Thread-0号生产线完成了一量火箭的组装!Thread内部也是通过执行Runnable接口的run()来运行线程
@Override public void run() { //此处的target是Runnable if (target != null) { target.run(); } }Daemon线程即守护线程,后台线程的特点是优先级比较低。当jvm中的非守护线程都运行结束的时候,那么Daemon守护线程也跟着结束。所以在使用守护线程的时候要慎重些
jvm的垃圾回收线程就是典型的(Daemon)守护线程。当jvm中没有其他的线程在运行时,垃圾回收线程也就跟着结束了
setDaemon一定要在线程的start之前设置,否则抛出IllegalThreadStateException异常
public static void main(String[] args) { Thread thread = new Thread(() -> { int num = 0; while (true) { try { Thread.sleep(20); System.out.println(Thread.currentThread().getName() + " is running!timestamp is " + System.currentTimeMillis() + " ,Daemon线程运行了" + num++ + "次"); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.setDaemon(true); thread.start(); try { Thread.sleep(500); Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("JVM运行结束,timestamp is " + System.currentTimeMillis()))); } catch (InterruptedException e) { e.printStackTrace(); } }Thread-0 is running!timestamp is 1489134646030 ,Daemon线程运行了0次 Thread-0 is running!timestamp is 1489134646050 ,Daemon线程运行了1次 Thread-0 is running!timestamp is 1489134646070 ,Daemon线程运行了2次 Thread-0 is running!timestamp is 1489134646090 ,Daemon线程运行了3次 Thread-0 is running!timestamp is 1489134646117 ,Daemon线程运行了4次 Thread-0 is running!timestamp is 1489134646137 ,Daemon线程运行了5次 Thread-0 is running!timestamp is 1489134646157 ,Daemon线程运行了6次 Thread-0 is running!timestamp is 1489134646177 ,Daemon线程运行了7次 Thread-0 is running!timestamp is 1489134646197 ,Daemon线程运行了8次 Thread-0 is running!timestamp is 1489134646217 ,Daemon线程运行了9次 Thread-0 is running!timestamp is 1489134646237 ,Daemon线程运行了10次 Thread-0 is running!timestamp is 1489134646257 ,Daemon线程运行了11次 Thread-0 is running!timestamp is 1489134646277 ,Daemon线程运行了12次 Thread-0 is running!timestamp is 1489134646297 ,Daemon线程运行了13次 Thread-0 is running!timestamp is 1489134646317 ,Daemon线程运行了14次 Thread-0 is running!timestamp is 1489134646337 ,Daemon线程运行了15次 Thread-0 is running!timestamp is 1489134646357 ,Daemon线程运行了16次 Thread-0 is running!timestamp is 1489134646377 ,Daemon线程运行了17次 Thread-0 is running!timestamp is 1489134646397 ,Daemon线程运行了18次 Thread-0 is running!timestamp is 1489134646417 ,Daemon线程运行了19次 Thread-0 is running!timestamp is 1489134646437 ,Daemon线程运行了20次 Thread-0 is running!timestamp is 1489134646457 ,Daemon线程运行了21次 Thread-0 is running!timestamp is 1489134646477 ,Daemon线程运行了22次 Thread-0 is running!timestamp is 1489134646497 ,Daemon线程运行了23次 JVM运行结束,timestamp is 1489134646511
Process finished with exit code 0 无论运行多少次,daemon线程中的时间戳永远小于主线程的,由此可见,当jvm中没有user线程在运行时,daemon线程也就跟着关闭了
在调用Thread实例start()方法后,基本状态为可执行状态(Runnable)、被阻塞状态(Blocked)、执行中(Running)几种状态 实例化Thread并执行start方法后,线程进入Runnable状态,此时线程尚未真正开始执行run()方法,必须等待排班器(Scheduler)插入cpu执行,线程才会执行run方法。 调用Thread.sleep()、进入synchronized前竞争对象锁定的阻断、调用wait()方法的阻断等、等待输入输出完成夜壶进入Blocked状态
输出为: 主线程开始运行 Thread B开始执行… Thread B执行中… Thread B执行中… Thread B执行中… Thread B执行中… Thread B执行中… Thread B将结束… 主线程将结束….
从上面的代码中,我们可以看到存在两个线程:主线程和线程Thread B
主线程调用线程Thread B的Join方法,导致主线程阻塞,直到Thread B线程执行完毕,才返回到主线程中。
简单理解,在主线程中调用Thread B.join(),也就是在主线程中加入了Thread B线程的代码,必须让Thread B线程执行完毕之后,主线程(调用方)才能j正常执行。
1.即刻停止run()方法中剩余的全部工作,包括在catch或finally语句中,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。
2.会立即释放该线程所持有的所有的锁,导致数据得不到同步的处理,出现数据不一致的问题。
public class Main{ public static void main(String [] args) throws Exception{ TestObject testObject = new TestObject(); Thread t1 = new Thread(){ public void run(){ try { testObject.print("1", "2"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; t1.start(); Thread.sleep(1000); t1.stop(); System.out.println("first : " + testObject.getFirst() + " " + "second : " + testObject.getSecond()); } } class TestObject{ private String first = "ja"; private String second = "va"; public synchronized void print(String first, String second) throws Exception{ this.first = first; Thread.sleep(10000); this.second = second; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getSecond() { return second; } public void setSecond(String second) { this.second = second; } } 输出first : 1 second : vasuspend()和resume()必须要成对出现,否则非常容易发生死锁。 因为suspend方法并不会释放锁,如果使用suspend的目标线程对一个重要的系统资源持有锁,那么没任何线程可以使用这个资源直到要suspend的目标线程被resumed,如果一个线程在resume目标线程之前尝试持有这个重要的系统资源锁再去resume目标线程,这两条线程就相互死锁了,也就冻结线程。
public class Main{ public static void main(String [] args) throws Exception{ TestObject testObject = new TestObject(); Thread t1 = new Thread(){ public void run(){ testObject.print(); } }; t1.setName("A"); t1.start(); Thread.sleep(1000); Thread t2 = new Thread(){ public void run(){ System.out.println("B已启动,但进入不到print方法中"); testObject.print(); } }; t2.setName("B"); t2.start(); } } class TestObject{ public synchronized void print(){ if(Thread.currentThread().getName().equals("A")){ System.out.println("A 线程 独占该资源了"); Thread.currentThread().suspend(); } } }当线程处于suspend状态下,此时如果调用destroy方法销毁线程,并不会释放锁,那么其他线程将不再能获取到它锁定的资源.
stop()方法不推荐使用了,那么我如果想要认为的让线程停止怎么办呢?
public class ThreadCustom implements Runnable { private boolean isContinue = true; @Override public void run() { while (isContinue) { System.out.println(Thread.currentThread().getName() + " is running!"); } } public void stop() { isContinue = false; } public static void main(String[] args) throws InterruptedException { ThreadCustom r = new ThreadCustom(); Thread thread = new Thread(r); thread.start(); Thread.sleep(500); r.stop(); } }