java多线程初步学习

start()

线程在调用该方法后,该线程会处于Runable状态,当该线程获取到cpu资源的时候就可以执行,与直接调用run不同,直接调用run函数其实就是函数的调用。

sleep()

调用该方法使当前线程暂停一段时间,让其他线程有机会得到执行,但该方法不会释放掉当前线程所拥有的对象锁,意思是其他线程的到运行机会时,也不能访问该线程的加锁内容,该方法需要捕获异常。

yield()

与sleep方法类似,但是不能指定暂停多长时间,也不能获得对象锁,并且只能让同优先级的线程获得运行机会。

class y1 extends Thread{
    public void run(){
        for (int i = 0; i < 20; i++) {
            System.out.println("----1----->");
            this.yield();

        }
    }
}
class y2 extends Thread{
    public void run(){
        for (int i = 0; i < 20; i++) {
            System.out.println("----2----->");
            this.yield();
        }
    }
}
public class TestYield {
    public static void main(String[] args){
        Thread yy1 = new y1();
        Thread yy2 = new y2();
        yy1.setPriority(1);
        yy2.setPriority(1);
        yy1.start();
        yy2.start();
    }
}
输出:
----2----->
----1----->
----2----->
----1----->
----2----->
----1----->
----2----->不一一列举

join()

当线程B调用的线程A的join方法,那么知道线程A执行完毕,线程B才有机会得到运行。

t.join();//调用join方法,等待t执行完毕;

t.join(1000);等待t运行,等待时间为1000ms;

如果调用的t.join之后,t还没有在运行,那么该调用无效。

另外:B调用A的join方法必须要拿到B的锁。

例一:

public class TestJoin implements Runnable {


    public static void main(String[] sure) throws InterruptedException {
        Thread t = new Thread(new TestJoin());
        long start = System.currentTimeMillis();
        t.start();
        t.join(1000);//等待线程t 1000毫秒
        System.out.println(System.currentTimeMillis()-start);//打印出时间间隔
        for (int i = 0; i < 20; i++) {
            System.out.println("main"+i);
        }
        System.out.println("Main finished");//打印主线程结束
    }

    @Override
    public void run() {
        //synchronized (currentThread()) {
        for (int i = 1; i <= 5; i++) {
            try {
                sleep(1000);//睡眠5秒,循环是为了方便输出信息
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("睡眠" + i);
        }
        System.out.println("TestJoin finished");//t线程结束
    }
    //}
}
输出:
1008
main0
main1
main2
main3
main4
main5
main6
main7
main8
main9
main10
main11
main12
main13
main14
main15
main16
main17
main18
main19
Main finished
睡眠1
睡眠2
睡眠3
睡眠4
睡眠5
TestJoin finished
上述例子可以看出:虽然主线程调用了t线程的join(1000)方法,但是并没有等t线程执行完毕。因为t线程处于runable状态并没有运行(睡眠1000ms),在等待了1008ms之后就自己先执行了。然后才执行t线程。

例二:

public class TestJoin implements Runnable {


    public static void main(String[] sure) throws InterruptedException {
        Thread t = new Thread(new TestJoin());
        long start = System.currentTimeMillis();
        t.start();
        t.join(1000);//等待线程t 1000毫秒
        System.out.println(System.currentTimeMillis()-start);//打印出时间间隔
        for (int i = 0; i < 20; i++) {
            System.out.println("main"+i);
        }
        System.out.println("Main finished");//打印主线程结束
    }

    @Override
    public void run() {
        //synchronized (currentThread()) {
        for (int i = 1; i <= 5; i++) {
            /*try {
                sleep(1000);//睡眠5秒,循环是为了方便输出信息
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            System.out.println("睡眠" + i);
        }
        System.out.println("TestJoin finished");//t线程结束
    }
    //}
}
上述:注销了t的sleep,所以在主线程执行join(1000)时,主线程等待了7ms之后,t进入了运行状态,于是便等待t运行完主线程才会运行。输出如下:
睡眠1
睡眠2
睡眠3
睡眠4
睡眠5
TestJoin finished
7
main0
main1
main2
main3
main4
main5
main6
main7
main8
main9
main10
main11
main12
main13
main14
main15
main16
main17
main18
main19
Main finished
例三:
public class TestJoin implements Runnable {


    public static void main(String[] sure) throws InterruptedException {
        Thread t = new Thread(new TestJoin());
        long start = System.currentTimeMillis();
        t.start();
        t.join(1000);//等待线程t 1000毫秒
        System.out.println(System.currentTimeMillis()-start);//打印出时间间隔
        for (int i = 0; i < 20; i++) {
            System.out.println("main"+i);
        }
        System.out.println("Main finished");//打印主线程结束
    }

    @Override
    public void run() {
        synchronized (currentThread()) {
        for (int i = 1; i <= 5; i++) {
            try {
                sleep(1000);//睡眠5秒,循环是为了方便输出信息
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("睡眠" + i);
        }
        System.out.println("TestJoin finished");//t线程结束
    }
    }
}
输出:
睡眠1
睡眠2
睡眠3
睡眠4
睡眠5
TestJoin finished
5003
main0
main1
main2
main3
main4
main5
main6
main7
main8
main9
main10
main11
main12
main13
main14
main15
main16
main17
main18
main19
Main finished
解释:因为主线程并没有得到t的锁,必须等t释放锁之后才会执行主线程。

锁池:

假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。

等待池:

假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁(因为wait()方法必须出现在synchronized中,这样自然在执行wait()方法之前线程A就已经拥有了该对象的锁),同时线程A就进入到了该对象的等待池中。如果另外的一个线程调用了相同对象的notifyAll()方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。如果另外的一个线程调用了相同对象的notify()方法,那么仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池.

例子:经典的消费者与生产者

class ShopMall {
    public static final int MAX_SIZE=5;
    public static final int MIN_SIZE=2;
    private int product;
    public synchronized void produce()
    {
        if(this.product >= MAX_SIZE)
        {
            try
            {
                System.out.println("仓库已满,请稍候再生产");
                wait();
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return;
        }
        this.product++;
        System.out.println("生产者生产第" + this.product + "个产品.");
        notifyAll();   //通知等待区的消费者可以取出产品了
    }

    /**
     * 消费者从店员取产品
     */
    public synchronized void consume()
    {
        if(this.product <= MIN_SIZE)
        {
            try
            {
                System.out.println("仓库缺货,稍候再取");
                wait();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            return;
        }
        System.out.println("消费者取走了第" + this.product + "个产品.");
        this.product--;
        notifyAll();   //通知等待去的生产者可以生产产品了
    }
}

class produce extends Thread{
    private ShopMall sm;
    public produce(ShopMall sm){
        this.sm=sm;
    }
    public void run(){
        while(true) {
            try{
                sm.produce();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
class consume extends Thread{
    private ShopMall sm;
    public consume(ShopMall sm){
        this.sm=sm;
    }
    public void run(){
        while(true){
            try{
                sm.consume();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}
public class ProAndCos{
    public static void main(String[] args){
        ShopMall sm = new ShopMall();
        Thread cos = new consume(sm);
        Thread pro = new produce(sm);
        cos.start();
        pro.start();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值