Java线程基本概念及操作

xiaoxiao2021-02-28  142

进程和线程         进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。线程可以理解为轻量级进程,是程序执行的最小单位。一个进程可以包含一个或者多个线程。

        线程的生命周期如下所示:

新建线程         方式一:继承Thread类,然后重写里面的run()方法。然后new一个对象,调用start()方法。

Thread t1 = new Thread(){ @Override public void run(){ System.out.println("Hello world!"); } }; t1.start();        方式二:MyThread实现Runnable接口,然后将MyThread对象作为Thread的构造器入参,创建Thread对象,然后调用start()方法。

Thread t1 = new Thread(new Runnable(){ @Override public void run(){ System.out.println("Hello Runnable!"); } }); t1.start(); 终止线程         通常来说,当我们启动一个线程后,都会让线程运行完成之后自动结束。可以通过Thread.stop()方法暴力终止线程,但是强烈不建议这样用。因为这样会造成程序的不可预测性,从而导致数据的不一致,而且不可恢复。 线程中断         线程中断是一种重要的线程协作机制。线程中断并不会使线程立即退出,而是给线程发送一个通知,告诉目标线程你可以退出了。其中主要包含以下3个API:

void Thread.interrupt();//中断线程 boolean Thread.isInterrupted;//判断是否被中断 static boolean Thread.interrupted();//判断是否被中断,并清除当前中断状态        当通知线程中断时,线程本身需要对中断做处理,否则对于线程的执行没有任何影响。 public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread() { @Override public void run() { while (true) { if(Thread.currentThread().isInterrupted()) { System.out.println("Interruted!"); break; } try { Thread.sleep(2000); } catch (Exception e) { System.out.println("Interrupted when sleep"); //设置中断状态 Thread.currentThread().interrupt(); } Thread.yield(); } } }; t1.setName("hugege"); t1.start(); Thread.sleep(2000); t1.interrupt(); System.out.println("main end"); } 等待和通知         说到线程的等待和通知,对应的基础的两个方法就是wait()、notify()方法。这两个方法并不在Thread当中,而是在Object中。当一个线程调用了object.wait(),那么它就会进入到object对象的等待队列。当object.notify()方法被调用时,就会从这个等待队列中随机选一个线程进行唤醒操作。并且这个过程是完全随机的。         object还有一个notifyAll()方法,这个方法是唤醒所有的线程,然后让这些线程去竞争执行,获得监视器对象的才可以继续往下执行。这里面需要注意的是不论是wait()还是notify(),执行前都需要获取到当前对象的监视器,也就是获得当前对象的锁。下面给出一个demo: /** * wait()和notify()使用 * */ public class SimpleWN { static final Object object = new Object(); public static class T1 extends Thread { @Override public void run() { synchronized (object) { System.out.println(System.currentTimeMillis()+":T1 start!"); try { System.out.println(System.currentTimeMillis()+"T1: wait for object "); object.wait(); } catch (Exception e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis()+":T1 end!"); } } } public static class T2 extends Thread { @Override public void run() { synchronized (object) { System.out.println(System.currentTimeMillis()+":T2 start! notify one thread"); object.notify(); System.out.println(System.currentTimeMillis()+"T2: end! "); try { Thread.sleep(2000); } catch (Exception e) { } } } } public static void main(String[] args) { Thread t1 = new T1(); Thread t2 = new T2(); t1.start(); t2.start(); } }        注意:Object.wait()和Thread.sleep()都可以让线程等待一段时间,Object.wait()是释放锁的,而Thread.sleep()是不释放锁的。 挂起和继续执行         这里面说线程挂起和继续执行分别指的是:suspend()和resume()方法。这里面挂起操作,是不释放锁资源的。查看JDK的文档会发现,这两个API已经被标记为过期了。所以在这里就不详细的介绍了。 等待线程结束和谦让         等待线程结束调用的方法是Thread.join(),JDK中提供了两个join方法: final void join() throws InterruptedException; final synchronized void join(long millis) throws InterruptedException;        如调用了t1.join(),则当前线程会无限等待t1线程,直到t1执行完成。第二个方法则增加了一个超时时间,超过了时间之后,则继续往下执行。其中t1.join()可以理解为,让t1加入到当前线程的串行执行。附demo如下: public class JoinMain { public volatile static int i = 0; public static class AddThread extends Thread { @Override public void run() { for(i = 0; i < 100000000; i++); } } public static void main(String[] args) throws InterruptedException { AddThread at = new AddThread(); at.start(); at.join(); System.out.println(i); } }        注意:t1.join()方法的本质是让主线程wait()在 t1 的对象实例上,当t1线程执行完成之后,会调用notifyAll(),从而唤醒主线程。所以在这里不要随意调用Thread.wait()和notify()方法,有可能扰乱join等方法的执行。         还有一个方法是Thread.yield(),这个方法是静态方法。Thread.yield()表示让当前线程让出CPU,然后再共同竞争CPU资源。这样只会增加别的线程执行的机会,而并不是当前线程一定不执行。 链接: http://moguhu.com/article/detail?articleId=23

转载请注明原文地址: https://www.6miu.com/read-33699.html

最新回复(0)