多线程之基础

进程和线程:
● 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1~n个线程。
● 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。

线程五状态.png

线程和进程一样分为五个阶段:

1.新建状态(New):新创建了一个线程对象。
2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3.运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4.阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
阻塞的情况分三种:
● 等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
● 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
● 其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5.死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

并行和并发:
● 并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时
● 并发:多个CPU实例或者多台机器在同一时间间隔发生。

创建任务的线程:

第一种是创建Thread子类的一个实例并重写run方法,不适合资源共享。
第二种是创建类的时候实现Runnable接口,则很容易的实现资源共享。
注意:start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。

//创建一个线程
Tread thread = new Thread();
thread.start();

//创建Thread子类的一个实例并重写run方法,run方法会在调用start()方法之后被执行。
public class MyThread extends Thread {
   public void run(){
     System.out.println("MyThread running");
   }
}

MyThread myThread = new MyThread();
myTread.start();

//创建一个Thread的匿名子类
Thread thread = new Thread(){
   public void run(){
     System.out.println("Thread Running");
   }
};
thread.start();
//新建一个实现了java.lang.Runnable接口的类的实例
public class MyRunnable implements Runnable {
   public void run(){
    System.out.println("MyRunnable running");
   }
}

Thread thread = new Thread(new MyRunnable());
thread.start();

//创建一个实现了Runnable接口的匿名类
Runnable myRunnable = new Runnable(){
   public void run(){
     System.out.println("Runnable running");
   }
}
Thread thread = new Thread(myRunnable);
thread.start();

如果同时重写Thread类和Runnable接口的run方法,上面执行的run方法到底是Runnable的还是Thread的呢?

public class ThreadTests {  
  
    public static void main(String[] args) {  
        new Thread(new Runnable(){  
            public void run() {  
                System.out.println("Thread Runing in Runnable...");  
            }  
        }){  
            public void run() {  
                System.out.println("Thread Runing in Parent Thread...");  
            }  
        }.start();  
    }  
}  

结果:Thread Runing in Parent Thread...
总结:查看Thread类的run()方法的源代码,可以看到其实这两种方式都是在调用Thread对象的run()方法,如果Thread类的run方法没有被覆盖,并且为该Thread对象设置了一个Runnable对象,该run方法会调用Runnable对象的run方法。即是先运行的Thread对象的run方法,如果Thread对象重写run方法,就去运行Thread的run方法。

提醒:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM实习在就是在操作系统中启动了一个进程。

public class Thread implements Runnable{

   /*暂停当前正在执行的线程对象,并执行其他线程。*/
   public static native void yield();
   /*将线程设置为休眠以确保其他线程执行,休息时间为毫秒。*/
   public static native void sleep(long millis) throws InterruptedException; 
   /*使一个线程等待另一个线程的结束*/
   public final void join() throws InterruptedException {
       join(0);
   }

   @Override
   public void run() {
       if (target != null) {
           target.run();
       }
   }
}

● sleep()和yield()的区别:
sleep()使当前线程进入停滞状态,所以执行sleep()的线程在指定的时间内肯定不会被执行;
yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
sleep方法允许较低优先级的线程获得运行机会
但 yield()方法执行时,当前线程仍处在可运行状态,所以,不可能让出较低优先级的线程些时获得 CPU 占有权。
● sleep()和wait()方法的最大区别是:
sleep()睡眠时,保持对象锁,仍然占有该锁;而wait()睡眠时,释放对象锁。

  • 线程等待:
    Object类中的wait()方法,导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 唤醒方法。
    Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用

  • 线程唤醒:Object类中的notify()方法,唤醒在此对象监视器上等待的单个线程。
    如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。
    选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容