cici-new

1 创建线程的方式

  •  扩展java.lang.Thread类
  •  实现Runnable接口

2 扩展java.lang.Thread类

用户的线程只需要继承Thread类,覆盖Thread类的run()方法即可。

 

Thread类代表线程类,最主要的两个方法

      run()   --- 包含线程运行时候所执行的代码 (没有任何异常抛出): public void run()

      start() --- 用于启动线程

例子:

package com.cici.extends;
public class Machine extends Thread{
   public void run(){
         for(int a=0;a<50;a++){
            System.out.println(a);
        }
  }
 public static void main(String[] args){
    Machine machine = new Machine();
    machine.start();
 }
}

2.1 用户自定义线程各自运行

    

public class Machine extends Thread{
    private int a;
    @Override
    public void run() {
        for( a=0;a<10;a++){
            System.out.println(currentThread().getName()+"----"+a);
            try {
                sleep(2000);//给其他线程运行机会
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Machine th1 = new Machine();
        Machine th2 = new Machine();
        th1.start();//th1线程启动
        th2.start();//th2线程启动
        th1.run();//主线程调用th1线程
    }

}

备注:从面向对象的角度来看,Thread类的run()方法是准们被自身线程执行的。主线程调用Thread类的run(),违背了Thread类提供的run()的初衷。

输出:
Thread-0----0
main----0
Thread-1----0
Thread-0----1
main----2
Thread-1----1
Thread-0----3
Thread-1----2
main----4
Thread-0----5
main----6
Thread-1----3
Thread-0----7
main----8
Thread-1----4

 

2.2 线程拥有各自的实例变量

 

public class Machine extends Thread{
    private int a;
    @Override
    public void run() {
        for( a=0;a<10;a++){
            System.out.println(currentThread().getName()+"----"+a);
            try {
                sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Machine th1 = new Machine();
        Machine th2 = new Machine();
        th1.start();
        th2.start();
    //    th1.run();
    }

}

 

输出结果

 

Thread-0----0
Thread-1----0
Thread-0----1
Thread-1----1
Thread-0----2
Thread-1----2
....
....
....

 

解释:

线程th1和线程th2用有各自的实例变量,运行各自的run()方法.

2.3 主线程与用户自定义线程并发运行

public class Machine_SHARE_ONE_INSTANCE extends Thread{
    private int a=0;
    @Override
    public void run() {
        for( a=0;a<10;a++){
            System.out.println(currentThread().getName()+"----"+a);
            try {
                sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Machine_SHARE_ONE_INSTANCE m1 = newMachine_SHARE_ONE_INSTANCE();
        m1.start();
        m1.run();
        
    }
}
//运行结果

main----0
Thread-0----0
Thread-0----1
main----2
main----3
Thread-0----4
Thread-0----6
main----6
Thread-0----7
main----8
main----9

 

 解释:

主线程和Machine线程都会执行Machine对象的run()方法。操纵同一个实例变量a。

3 实现Runnable接口

java.lang.Runnable接口,最主要的两个方法

      run()   --- 包含线程运行时候所执行的代码 (没有任何异常抛出): public void run()

      start() --- 用于启动线程

 Thread 线程类也实现了 Runnable接口,并有如下的构造方法:public Thread(Runnable target)

public class Machine_Runnable implements Runnable{

    private int a=0;
    public void run() {
        for(a=0;a<10;a++){
            System.out.println(Thread.currentThread().getName()+":"+a);
            
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Machine m = new Machine();
        Thread t1 = new Thread(m);
        t1.start();
    }
}

 

 4 Exercise:
    4.1 以下代码能否编译通过?如果通过将得到什么打印结果?

1 public class WhatHappens implements Runnable{
2     public static void main(String[] args) {
3        Thread t = new Thread(this);
4         t.start();
5     }
6     public void run() { 
7         System.out.println("HI");
8     }
9 }

不能line3 出现错误:原因不能再static静态方法内使用 this关键字

 4.2 能否编译通过?打印什么内容?

OK

public class WhatHappens implements Runnable{
    public static void main(String[] args) {
        WhatHappens wh = new WhatHappens();
        wh.run();
    }
    public void run() {
        for(int i=0;i<10;i++){
            System.out.println("Value of i :  "+i);
        }
    }
} 
Value of i :  0
Value of i :  1
Value of i :  2
Value of i :  3
Value of i :  4
Value of i :  5
Value of i :  6
Value of i :  7
Value of i :  8
Value of i :  9

4.3 Line 5 出现什么代码会 打印出RUNING ?

 1 public class RunTest implements Runnable{
 2     public static void main(String[] args) {
 3         RunTest rt = new RunTest();
 4         Thread th = new Thread(rt);
 5         //??
 6     }
 7     public void run() {
 8         System.out.println("RUNING");
 9     }
10     void go(){
11         start(1);
12     }
13     private void start(int i) {}
14 }
 th.start();
 th.run();
 rt.run();

4.4 下列代码能否编译通过?

public class Test {
    public static void main(String[] args) {
        Thread th = new Thread(new RunHandler());
        th.start();
    }
}
class RunHandler{
    public void run(){
        System.out.println("RUNING");
    }
}

不能RunHander没有实现Runable接口

4.5 假设某银行服务器内存储了1000块钱的数据信息,现有两台ATM同时取款,一个取800,一个取700,用多线程解决同时取款的问题

参考出自http://sd6292766.iteye.com/blog/695814

谢谢sd6292766

 1 public class TestAccount {
 2     public static void main(String[] args) {
 3         /*临界资源 */
 4         Account account = new Account();
 5         Withdraw  w1= new Withdraw (700);
 6         w1.account=account;
 7         Withdraw  w2= new Withdraw (800);
 8         w2.account=account;
 9         w1.start();
10         w2.start();
11      }
12 }
13 class Withdraw  extends Thread{
14     public Account account;
15     private int withdrawMoney;
16     public Withdraw (int money){
17         this.withdrawMoney = money;
18     }
19     public void run(){
20         System.out.println(this.getName()+" 来取"+ withdrawMoney+"块钱");
21         account.withdraw (withdrawMoney);
22         System.out.println("余额为:"+account.getBalance()+"  元!");
23     }
24 }
25 class Account {
26     private float balance =1000;
27     public float getBalance() {
28         return balance;
29     }
30 
31     public void setBalance(float balance) {
32         this.balance = balance;
33     }
34     /*取款 同步*/
35     public synchronized void withdraw(float money){
36         if(balance>=money) {
37             System.out.println("被取走"+money+"元");
38             try {
39                 Thread.sleep(1000);
40             } catch (InterruptedException e) {
41                 e.printStackTrace();
42             }
43         balance -=money;
44     }else{
45         System.out.println("对不起 余额不足");
46     }
47 }
48     
49 }

 

 5 线程状态

5.1 新建状态
new语句创建线程对象处于新建状态
5.2 就绪状态
当一个线程对象创建之后 其他线程调用它的start()方法 该线程进入就绪状态
5.3 运行状态
处于这个状态的线程占用CPU 执行程序代码
5.4 阻塞状态
 1)位于对象等待池中的阻塞状态:线程位于运行状态时,如果执行了某个对象的wait().JVM就会把线程放入这个对象的等待池当中。
 wait():执行该方法的线程释放对象的锁,JVM就会把线程放入这该对象的等待池当中,等待其他线程将其唤醒。
 2)位于对象琐池中的阻塞状态:当前线程处于运行状态时,试图获得某个对象的同步锁时,如果该对象的该对象的同步锁已经被其他线程占用,
 JVM就把这个线程放到这个对象的锁池当中。
 *解释每个java对象只有一个同步锁,在任何时刻,最多允许一个线程拥有这把锁。当消费者线程试图执行以上带有synchronized(this)
 标记的代码块时,消费者线程必须先获得this关键字引用的Stack对象的锁。
  --1 假如这个锁已经被其他线程占用,JVM把消费者线程放到Stack对象的锁池中,消费者线程进入阻塞状态。在Stack对象的锁池中
         可能会有许多等待锁得线程,等其他线程释放了锁,JVM从锁池中随机取出一个线程,是这个线程拥有锁。该线程到就绪状态。
  --2 假如这个锁没有被其他线程占用,消费者就会获得这把锁,并执行同步代码块。一般消费者线程只有执行完同步代码块,才释放锁。
  3)其他阻塞状态:当执行了sleep()方法,或者调用了其他线程的join() 或者发出IO请求时 就会进入这个状态
5.5 死亡状态 Dead
线程退出run() 就进入死亡状态 该线程生命周期结束

 6 什么时候持有锁的线程会释放锁
1 执行完同步代码块
2 执行同步代码块过程中 遇到异常导致线程终止 锁会被释放
3 执行同步代码块过程中 执行了锁所属对象的wait()方法 线程释放锁 进入对象等待池中


下列情况不会释放锁
1 执行同步代码块过程中 执行了Thread.sleep()方法
当前线程放弃CPU 开始睡眠 在睡眠中不释放锁
2 执行同步代码块过程中 执行了Thread.yield()方法
当前线程放弃CPU 开始睡眠 在睡眠中不释放锁

7 Thread类静态方法比较

wait() 执行该方法的线程 释放对象锁 JVM把该线程放到该对象的等待池中。该线程等待其他线程将它唤醒。
notify()执行该方法的线程 唤醒在对象的等待池中等待的一个线程。
JVM随机从对象的等待池中选择一个线程 把他转到对象的锁池中。

sleep()
yield()
相同
都是Thread类的静态方法 会使当前处于运行状态的线程
放弃CPU 把运行机会让给其他线程
差异 1
sleep() 给其他线程机会 而不考虑线程优先级
yield() 只会给同等优先级 或者更高优先级的线程一个机会
差异 2
线程执行了sleep(long millis)方法后,转到阻塞状态
执行yield()方法后转到就续状态
差异 3
sleep() --- 抛出InterruptedException异常
yield() --- 不抛出任何异常
差异 4
sleep()方法移植性能好
yield()方法用途:测试期间人为提高程序并发性能 帮助查询
隐含错误

 

分类:

技术点:

相关文章:

  • 2022-01-01
  • 2021-11-04
  • 2021-10-08
  • 2021-09-25
  • 2021-12-29
  • 2022-01-01
  • 2021-11-04
  • 2021-11-13
猜你喜欢
  • 2022-01-01
  • 2022-01-01
  • 2022-01-01
  • 2021-08-01
  • 2021-10-10
  • 2021-11-07
相关资源
相似解决方案