黑马程序员5 多线程

创建线程的第一种方式:继承Thread类。
步骤:
1,定义类继承Thread。
2,复写Thread类中的run方法。
目的:将自定义代码存储在run方法。让线程运行。

3,调用线程的start方法,
该方法两个作用:启动线程,调用run方法。

创建线程的第二种方式:实现Runable接口

步骤:
1,定义类实现Runnable接口
2,覆盖Runnable接口中的run方法。
将线程要运行的代码存放在该run方法中。

3,通过Thread类建立线程对象。
4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
为什么要将Runnable接口的子类对象传递给Thread的构造函数。
因为,自定义的run方法所属的对象是Runnable接口的子类对象。
所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。

5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

实现方式和继承方式有什么区别呢?

实现方式好处:避免了单继承的局限性。
在定义线程时,建立使用实现方式。

两种方式区别:
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存在接口的子类的run方法。

范例:

public class Test1 {
    public static void main(String[] args) {
        for(int i=0;i<3;i++){
             new Thread(new Mess()).start();
        }
    }
}

class Mess implements Runnable{
    private static int taskcount = 0;
    private final int id = taskcount ++;
    Mess(){
        System.out.println("new message"+id);
    }
    @Override
    public void run() {
        System.out.println("r1:"+id);
        Thread.yield();  //对线程调度器的一种建议
        System.out.println("r2:"+id);
        Thread.yield();
        System.out.println("r3:"+id);
        Thread.yield();
        System.out.println("end"+id);
    }
}

=========================================================

Java对于多线程的安全问题提供了专业的解决方式。

就是同步代码块。

synchronized(对象)
{
需要被同步的代码

}
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。


同步规则(何时使用同步):如果正在写一个变量,他可能接下来被另一个线程读取,或者正在读取一个上一次已经被另一个线程写过的变量,必须使用同步,并且,读写线程都必须用相同的监视器锁同步。


同步函数的锁是this
静态同步函数的锁是Class对象。

 

public class Test1 {
    public static void main(String[] args) {
        for(int i=0;i<3;i++){
             new Thread(new Mess()).start();
        }
    }
}

class Mess implements Runnable{
    private static int taskcount = 0;
    private final int id = taskcount ++;
    Mess(){
        System.out.println("new message"+id);
    }
    @Override
    public void run() {
        System.out.println("r1:"+id);
        Thread.yield();  //对线程调度器的一种建议
        System.out.println("r2:"+id);
        Thread.yield();
        System.out.println("r3:"+id);
        Thread.yield();
        System.out.println("end"+id);
    }
}

=======================================================

等待/唤醒机制
涉及的方法:
1.wait():让线程处于冻结状态,被wait的线程会被存储到线程池中。
2.notify():唤醒线程池中的一个线程(任意)。
3.notifyAll():唤醒线程池中的所有线程。

这些方法都必须定义在同步中,因为这些方法是用于操作线程状态的方法,
必须要明确到底操作的是哪个锁上的线程。

为什么操作线程的方法 wait、notify、notifyAll定义在了Object类中?
因为这些方法是监视器的方法,监视器其实就是锁。
锁可以是任意的对象,任意的对象调用的方法一定定义在Object类中。

========================================================
Lock接口
将同步和锁封装成了对象,并将操作锁的方式定义到了该对象中,将隐式动作变成了显式动作。
Lock lock=new ReentrantLock();
lock.lock();//获取锁
code...;//throw Exception();
lock.unlock();//释放锁
try
{
lock.lock();//获取锁
}
finally
{
lock.unlock;//释放锁
}

Lock接口:它的出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成了显式锁操作;
同时更为灵活,可以一个锁上加上多组监视器。
lock();获取锁
unlock();释放锁,通常需要定义到finally代码块中。

Condition接口:它的出现替代了Object中的wait、notify、notifyAll方法。
将这些监视器方法单独进行了封装,变成了Condition监视器对象,
可以和任意锁组合。
await();//等待
signal();//唤醒一个等待线程
signalAll();//唤醒所有等待线程

import java.util.concurrent.locks.*;

class ProducerConsumerDemo2 
{
    public static void main(String[] args) 
    {
        Resource r = new Resource();

        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);

        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(pro);
        Thread t3 = new Thread(con);
        Thread t4 = new Thread(con);

        t1.start();
        t2.start();
        t3.start();
        t4.start();

    }
}
class Resource
{
    private String name;
    private int count = 1;
    private boolean flag = false;
            //  t1    t2
    private Lock lock = new ReentrantLock();

    private Condition condition_pro = lock.newCondition();
    private Condition condition_con = lock.newCondition();



    public  void set(String name)throws InterruptedException
    {
        lock.lock();
        try
        {
            while(flag)
                condition_pro.await();//t1,t2
            this.name = name+"--"+count++;

            System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
            flag = true;
            condition_con.signal();
        }
        finally
        {
            lock.unlock();//释放锁的动作一定要执行。
        }
    }


    //  t3   t4  
    public  void out()throws InterruptedException
    {
        lock.lock();
        try
        {
            while(!flag)
                condition_con.await();
            System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
            flag = false;
            condition_pro.signal();
        }
        finally
        {
            lock.unlock();
        }
        
    }
}

class Producer implements Runnable
{
    private Resource res;

    Producer(Resource res)
    {
        this.res = res;
    }
    public void run()
    {
        while(true)
        {
            try
            {
                res.set("+商品+");
            }
            catch (InterruptedException e)
            {
            }
            
        }
    }
}

class Consumer implements Runnable
{
    private Resource res;

    Consumer(Resource res)
    {
        this.res = res;
    }
    public void run()
    {
        while(true)
        {
            try
            {
                res.out();
            }
            catch (InterruptedException e)
            {
            }
        }
    }
}

===============================================================================

interrupt() 将处于强制冻结状态的线程,恢复到运行状态并处理InterruptedException

public class InterruptDemo {
    public static void main(String[] args) {
        Thread t = new Thread(new Demo());
        t.start();
        System.out.println("Start");
        t.interrupt();
    }
}

class Demo implements Runnable{
    private boolean flag  = true;
    @Override
    public synchronized void run() {
        while(flag){
            try {
                wait();
            } catch (InterruptedException e) {
                System.out.println("interrupted");
                flag = false;//通过修改标志位,让线程停止
            }
        }
        System.out.println("end");
    }
}

======================================================= 

守护线程: t1.setDaemon(true);
t1.start();
将线程声明为守护线程。(当前台线程停止时,守护线程强行停止)


join:
当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。
join可以用来临时加入线程执行。

class Demo2 implements Runnable
{
    public void run()
    {
        for(int x=0; x<70; x++)
        {
            System.out.println(Thread.currentThread().toString()+"....."+x);
            Thread.yield();
        }
    }
}

public class JoinDemo
{
    public static void main(String[] args) throws Exception
    {
        Demo2 d = new Demo2();
        Thread t1 = new Thread(d);
        t1.start();
        t1.join();
        for(int x=0; x<40; x++)
        {
            System.out.println("main....."+x);
        }
        System.out.println("over");
    }
}

优先级:setPriority(Thread.MAX_PRIORITY);//设置到最高优先级
线程组:每个线程属于其创建者所在的线程组。调用线程的toString方法可以看到其线程组。

 

posted @ 2012-10-19 22:21  EnderViking  阅读(128)  评论(0)    收藏  举报