更新時間:2018-11-26 來源:黑馬程序員 瀏覽量:
【創建多線程的第一種方式:--繼承Thread類】
1:定義一個類繼承Thread類
2:重寫Thread類中的run方法
3:創建該類的實例,并調用start方法。
【start方法的作用】:A、啟動線程。B、調用run方法
1、模擬一個多線程:
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、匿名內部類的線程實現方式:
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、模擬一個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);
}
}
}
-------------------------------------------------------------------------------------------------------
【創建線程的第二種方式:--實現Runnable接口】
1、實現Runnable接口
2、重寫Runnable接口中的run方法
3、將Runnable接口中的子類對象作為實際參數,傳遞給Thread類的構造方法
4、調用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、模擬賣票系統【實現Runnable接口】
public class Demo{
public static void main(String[] args){
MyRunTick mt = new MyRunTick();
Thread t1 = new Thread(mt,"一號窗口");
Thread t2 = new Thread(mt,"二號窗口");
Thread t3 = new Thread(mt,"三號窗口");
Thread t4 = new Thread(mt,"四號窗口");
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+"號票");
try{
Thread.sleep(1);
}catch(InterruptedException e){
e.printStackTrace();
}
ticket--;
}else{
System.out.println(Thread.currentThread().getName()+"票已賣完。。");
break;
}
}
}
}
}
總結:同步的前提是必須有兩個或者兩個以上的線程,多個線程使用的是同一個鎖。
線程同步的前提:1、必須是多個線程使用同一個鎖;
2、必須保證同步中只能有一個線程在運行
-------------------------------------------------------------------------------------------------------
1、實現方式和繼承方式有什么區別?
實現的好處是:避免了單繼承的局限性。---->> 定義線程的時候最好使用實現方式
區別是:繼承Thread線程的代碼存放在Thread子類的run()方法中;
實現Runnable線程的代碼存放在接口子類的run()方法中。
2、什么是鎖對象?如何創建?如何獲得?
每個Java對象都有一個鎖對象,而且只有一把鑰匙;
可以使用this關鍵字作為鎖對象,也可以使用所在類的字節碼文件對應的Class對象作為鎖對象;
可以通過:類名.class 或者 對象.Class() 獲得。
3、同步的使用?
只能同步方法(代碼塊),不能同步類或者變量。
4、如何解決《生產者與消費者》的問題?
可以通過一個標記,表示數據的存儲空間狀態。
【代碼如下:】
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,"生產者");
Thread t2 = new Thread(con,"消費者");
t1.start();
t2.start();
}
}
// 使用Person作為數據存儲空間
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();
}
}
// 生產者
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++;
}
}
}
// 消費者
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()?
因為如果只用notify()的話,容易出現只喚醒本方線程的情況,導致程序中的所有線程都在等待。