進程A和進程B的內(nèi)存獨立不共享。
線程A和線程B在Java語言中抄腔,線程A和線程B瓢湃,堆內(nèi)存和方法區(qū)內(nèi)存共享理张,但棧內(nèi)存獨立,一個線程一個棧
假設(shè)啟動10個線程绵患,會有10個椢戆龋空間,每個棧和每個棧之間落蝙,互不干擾织狐,各自執(zhí)行各自的,這就是多線程并發(fā)筏勒,Java之所以有多線程機制移迫,目的就是為了提高程序的處理效率
Java語言中,實現(xiàn)線程有兩種方式
第一種:編寫一個類管行,直接繼承java.lang.Thread厨埋,重寫run方法。
public class ThreadTest02
{
public static void main(String[] args)
{
//這里是main方法捐顷,這里的代碼屬于主線程揽咕,在主棧中運行。
//新建一個分支線程對象
MyThread myThread=new MyThread();
//啟動線程
//start()方法的作用是:啟動一個分支線程套菜,在JVM中開辟一個新的棧空間设易,這段代碼在任務(wù)完成之后瞬間就結(jié)束了
//這段代碼的任務(wù)只是為了開啟一個新的椂翰瘢空間,只要新的椂俜危空間開出來戏溺,start()方法就結(jié)束了,線程就啟動成功了
//啟動成功的線程會自動調(diào)用run方法屠尊,并且run方法在分支棧的棧底部(壓棧)
//run方法在分支棧的棧底部旷祸,main方法在主棧的棧底部,run和main是平級的
myThread.start();
//這里的代碼還是運行在主線程中
for (int i = 0; i < 1000; i++) {
System.out.println("主線程---->"+i);
}
}
}
class MyThread extends Thread {
@Override
public void run()
{
//編寫程序讼昆,這段程序運行在分支線程中(分支線)
for(int i=0;i<1000;i++){
System.out.println("分支線程---->"+i);
}
}
}
第二種:編寫一個類托享,實現(xiàn)java.lang.Runnable接口,實現(xiàn)run方法浸赫。
public class ThreadTest03
{
public static void main(String[] args)
{
//創(chuàng)建一個可運行的對象
MyRunnable myRunnable=new MyRunnable();
//將可運行的對象封裝成一個線程對象
Thread thread=new Thread(myRunnable);
//啟動線程
thread.start();
for (int i = 0; i < 100; i++) {
System.out.println("主線程--->"+i);
}
}
}
class MyRunnable implements Runnable{
@Override
public void run()
{
for (int i = 0; i < 100; i++) {
System.out.println("支線程--->"+i);
}
}
}
匿名內(nèi)部類方式
public class ThreadTest04
{
public static void main(String[] args)
{
//創(chuàng)建線程對象闰围,采用匿名內(nèi)部類方式
//這是通過一個沒有名字的類,new出來的對象
Thread thread=new Thread(new Runnable(){
@Override
public void run()
{
for (int i = 0; i < 100; i++) {
System.out.println("thread線程--->"+i);
}
}
});
thread.start();
for (int i = 0; i < 100; i++) {
System.out.println("main線程--->"+i);
}
}
}
線程的生命周期
線程名字
1既峡、獲取線程對象名字:
String name = 線程對象.getName();
2羡榴、設(shè)置線程對象名:
線程對象.setName("線程名字");
3、若沒有給線程對象設(shè)置名字時运敢,默認的名字有什么規(guī)律校仑?
Thread-0
Thread-1
Thread-2
······
4忠售、獲取當前線程對象
Thread t= Thread.currentThread();
返回值t就是當前線程
關(guān)于線程的sleep方法:
static void sleep(long millis)
1、靜態(tài)方法:Thread.sleep(1000);
2迄沫、參數(shù)時毫秒
3稻扬、作用:讓讓當前線程進入休眠,進入”阻塞狀態(tài)“邢滑,放棄占有CPU時間片腐螟,讓給其他線程使用。
這行代碼出現(xiàn)在A線程中困后,A線程就會進入休眠乐纸。
這行代碼出現(xiàn)在B線程中,B線程就會進入休眠摇予。
4汽绢、Thread.sleep()方法,可以做到這種效果
間隔特定的事件侧戴,去執(zhí)行一段特定的代碼宁昭,每隔多久執(zhí)行一次。
關(guān)于sleep的面試題
public class ThreadTest06
{
public static void main(String[] args)
{
Thread t=new MyThread3();
t.setName("t");
t.start();
try {
t.sleep(1000*5);//在執(zhí)行的時候還是會轉(zhuǎn)換成:Thread.sleep(1000*5);
//這行代碼的作用市:讓當前線程進入休眠酗宋,也就是說main線程進入休眠
//這樣代碼出現(xiàn)在main方法中积仗,main線程睡眠
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello,world");
}
}
class MyThread3 extends Thread{
public void run(){
for (int i = 0; i < 10; i++) {
System.out.println("支線程--->"+i);
}
}
}
重點:run()當中的異常不能throw,只能try蜕猫,catch
因為run()方法在父類中沒有拋出任何異常寂曹,子類不能比父類拋出更多的異常
將正在睡眠的線程喚醒(終止)
public class ThreadTest07
{
public static void main(String[] args)
{
Thread t=new Thread(new MyRunnable2());
t.setName("t");
t.start();
//終斷t線程的睡眠(這種終斷睡眠的方式依靠了java的異常處理機制)
t.interrupt();
}
}
class MyRunnable2 implements Runnable{
@Override
public void run()
{
System.out.println(Thread.currentThread().getName()+"--->begin");
try {
Thread.sleep(1000*60*60*24*365);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"--->end");
}
}
依靠的是Java異常處理機制,當執(zhí)行t.interrupt()方法回右,會使run中的Thread.sleep(1000606024365);語句報錯隆圆,打印錯誤,整個try/catcha結(jié)構(gòu)結(jié)束翔烁。
合理的終止一個線程的方法
public class ThreadTest08
{
public static void main(String[] args)
{
MyRunnable3 r3=new MyRunnable3();
Thread t=new Thread(r3);
t.setName("t");
t.start();
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
r3.flag=false;
}
}
class MyRunnable3 implements Runnable{
boolean flag=true;
@Override
public void run()
{
for (int i = 0; i < 100; i++) {
if (flag){
System.out.println(Thread.currentThread().getName()+"--->"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
return;
}
}
}
}
合并線程
class MyThread1 extends Thread {
public void doSome(){
MyThread2 t=new MyThread2();
t.join();//當前線程進入阻塞渺氧,t線程執(zhí)行,直到t線程結(jié)束蹬屹,當前線程才可以執(zhí)行
}
}
class MyThread2 extends Thread{
}
package thread;
public class ThreadTest09
{
public static void main(String[] args)
{
System.out.println("main 啟動");
Thread thread=new Thread(new MyRunnable4());
thread.setName("t");
thread.start();
try {
thread.join();//將thread合并到當前線程中侣背,使當前線程阻塞,thread線程執(zhí)行直到結(jié)束
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main 關(guān)閉");
}
}
class MyRunnable4 implements Runnable{
@Override
public void run()
{
for (int i = 0; i < 1000; i++) {
String name=Thread.currentThread().getName();
System.out.println(name+"--->"+i);
}
}
}
join()語句使兩個棧之間發(fā)生的