更新時(shí)間:2018-11-26 來(lái)源:黑馬程序員 瀏覽量:
【創(chuàng)建多線程的第一種方式:--繼承Thread類】
1:定義一個(gè)類繼承Thread類
2:重寫Thread類中的run方法
3:創(chuàng)建該類的實(shí)例,并調(diào)用start方法。
【start方法的作用】:A、啟動(dòng)線程。B、調(diào)用run方法
1、模擬一個(gè)多線程:
class MyThread extends Thread{
public void run(){
for(int i=1;i<500;i++){
System.out.println("MyThread:"+i);
}
}
}
public class Demo1{
public Static void main(String[] args){
MyThread my = new MyThread();
my.start();
for(int j=1;j<500;j++){
System.out.println("main:"+i);
}
}
}
2、匿名內(nèi)部類的線程實(shí)現(xiàn)方式:
public class Demo2{
public static void main(String[] args){
new Thread{
public void run(){
for(int=i;i<100;i++){
System.out.println("MyThread:"=i);
}
}
}.start;
}
for(int i=1;i<100;i++){
System.out.println("main:"+i);
}
}
3、模擬一個(gè)QQ聊天的線程:
class Video extends Thread{
public void run(){
while(true){
System.out.println("視頻中...");
}
}
}
class Talk extends Thread{
public void run(){
while(true){
System.out.println("聊天中...");
}
}
}
public class Demo3{
public static void main(String[] args){
Video v = new Video();
Talk t = new Video();
v.start();
t.start();
for(int i=1;i<100;i++){
System.out.println("main:"+i);
}
}
}
-------------------------------------------------------------------------------------------------------
【創(chuàng)建線程的第二種方式:--實(shí)現(xiàn)Runnable接口】
1、實(shí)現(xiàn)Runnable接口
2、重寫Runnable接口中的run方法
3、將Runnable接口中的子類對(duì)象作為實(shí)際參數(shù),傳遞給Thread類的構(gòu)造方法
4、調(diào)用Thread類中的start方法開啟線程
1、public class Demo1{
public static void main(String[] args){
MyRun my = new MyRun();
Thread t = new Thread(my);
t.start();
for(int i=1;i<100;i++){
System.out.println("main:"+i);
}
}
}
class MyRun implements Runnable{
public void run(){
for(int i=1;i<100;i++){
System.out.println("MyRun:"+i);
}
}
}
2、模擬賣票系統(tǒng)【實(shí)現(xiàn)Runnable接口】
public class Demo{
public static void main(String[] args){
MyRunTick mt = new MyRunTick();
Thread t1 = new Thread(mt,"一號(hào)窗口");
Thread t2 = new Thread(mt,"二號(hào)窗口");
Thread t3 = new Thread(mt,"三號(hào)窗口");
Thread t4 = new Thread(mt,"四號(hào)窗口");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class MyRunTicket implements Runnable{
private int ticket = 100;
public void run(){
while(true){
synchronized(this){
if(ticket > 0){
System.out.println(Thread.currentThread().getName()+"賣:"+this.ticket+"號(hào)票");
try{
Thread.sleep(1);
}catch(InterruptedException e){
e.printStackTrace();
}
ticket--;
}else{
System.out.println(Thread.currentThread().getName()+"票已賣完。。");
break;
}
}
}
}
}
總結(jié):同步的前提是必須有兩個(gè)或者兩個(gè)以上的線程,多個(gè)線程使用的是同一個(gè)鎖。
線程同步的前提:1、必須是多個(gè)線程使用同一個(gè)鎖;
2、必須保證同步中只能有一個(gè)線程在運(yùn)行
-------------------------------------------------------------------------------------------------------
1、實(shí)現(xiàn)方式和繼承方式有什么區(qū)別?
實(shí)現(xiàn)的好處是:避免了單繼承的局限性。---->> 定義線程的時(shí)候最好使用實(shí)現(xiàn)方式
區(qū)別是:繼承Thread線程的代碼存放在Thread子類的run()方法中;
實(shí)現(xiàn)Runnable線程的代碼存放在接口子類的run()方法中。
2、什么是鎖對(duì)象?如何創(chuàng)建?如何獲得?
每個(gè)Java對(duì)象都有一個(gè)鎖對(duì)象,而且只有一把鑰匙;
可以使用this關(guān)鍵字作為鎖對(duì)象,也可以使用所在類的字節(jié)碼文件對(duì)應(yīng)的Class對(duì)象作為鎖對(duì)象;
可以通過(guò):類名.class 或者 對(duì)象.Class() 獲得。
3、同步的使用?
只能同步方法(代碼塊),不能同步類或者變量。
4、如何解決《生產(chǎn)者與消費(fèi)者》的問(wèn)題?
可以通過(guò)一個(gè)標(biāo)記,表示數(shù)據(jù)的存儲(chǔ)空間狀態(tài)。
【代碼如下:】
pulibc class Demo{
public static void main(String[] args){
Persion p = new Person();
Producer pro = new Prodecer();
Consumer con = new Consumer();
Thread t1 = new Thread(pro,"生產(chǎn)者");
Thread t2 = new Thread(con,"消費(fèi)者");
t1.start();
t2.start();
}
}
// 使用Person作為數(shù)據(jù)存儲(chǔ)空間
class Person{
String name;
String gender;
boolean flag = false;
public synchronized void set(String name,String gender){
if(flag){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
this.name = name;
this.gender = gender;
flag = true;
notify();
}
public synchronized void read(){
if(!flag){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println("name:"+this.name+"----gender:"+this.gender);
flag = false;
notify();
}
}
// 生產(chǎn)者
class Producer implements Runnable{
Person p;
public Producer(){
}
public Producer(Person p ){
this.p = p;
}
public void run(){
int i = 0;
while(trues){
if(i%2=0){
p.set("jack","man");
}else{
p.set("小麗","女");
}
i++;
}
}
}
// 消費(fèi)者
class Consumer implements Runnable{
Person p;
public Consumer(){
}
public Consumer(Person p){
this.p = p;
}
public void run(){
while(true){
p.read();
}
}
}
5、在Object類中,wait()和sleep()有什么卻別?
wait() 是Object中的方法,表示:釋放資源,釋放鎖。
sleep()是Thread中的方法,表示:釋放資源,不釋放鎖。
6、為什么定義了notify(),還要再定義notifyAll()?
因?yàn)槿绻挥胣otify()的話,容易出現(xiàn)只喚醒本方線程的情況,導(dǎo)致程序中的所有線程都在等待。
首發(fā): http://java.itheima.com