首页 > 代码库 > Java多线程与并发库高级应用

Java多线程与并发库高级应用

1.传统线程机制的回顾

  1.1创建线程的两种传统方式

  在Thread子类覆盖的run方法中编写运行代码

// 1.使用子类,把代码放到子类的run()中运行
        Thread thread = new Thread() {
            @Override
            public void run() {

                while (true) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName());
                }

            }
        };
        thread.start();

   >涉及一个以往的知识点:能否在run方法声明上抛出异常,以便省略run方法内部对Thread.sleep()语句的try...catch处理InterrunptedException?

在覆写祖先类方法或实现接口方法(覆写run方法,而本源run方法没有做抛出声明),所以你无法做抛出声明

  在传递给Thread对象的Runnable对象的run方法中编写代码

  

  

public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

 

在init方法中对Thread对象的target进行复制

Thread的run方法

/**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object‘s <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

 

//2.代码放在Runnable对象中,Runnable是代码运行的宿主
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName());
                }

            }
        });
        thread2.start();

 

  >问题:如果在Thread子类覆盖的run方法总编写了运行代码,也为Thread子类对象传递了一个Runnable对象,那么,线程执行的是哪个run方法?
   子类的run()覆盖了父类的run(),如果没有覆盖父类的run(),会找Runnable 
 

//3.使用的是子类中的run方法
        new Thread(new Runnable() {
            
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("runnable :"+Thread.currentThread().getName());
                }
            }
        }){
            public void run() {
                while(true){
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("thread :"+Thread.currentThread().getName());
                }
            };
        }.start();

  

  >涉及到一个以往的知识点:匿名内部类对象的构造方法如何调用父类的非默认构造方法?

  >多线程机制会提高程序的运行效率么?

    单个cpu下不会提高运行效率,反而性能更低

 

 Java中sleep和wait的区别

① 这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类。

sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

② 锁: 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。

Thread.sleep(0)的作用是“触发操作系统立刻重新进行一次CPU竞争”。

③ 使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用。

synchronized(x){
x.notify()
//或者wait()
}

 

2.传统定时器技术回顾(jdk1.5以前)

   

public class TraditionalTimerTest {
    static int count = 0;
    public static void main(String[] args) {
        
        //10秒后开始执行,每隔3秒执行一次
        new Timer().schedule(new TimerTask() {
            
            @Override
            public void run() {
                System.out.println("bombing...");
                
            }
        }, 10000,3000);
        
        /**
         *  需求:2秒,4秒间隔执行定时任务
         */
        class MyTimerTask extends TimerTask{
            @Override
            public void run() {
                count = (count+1)%2;
                System.out.println("bombing...");
                new Timer().schedule(new MyTimerTask(), 2000 + 2000*count);
            }
        }
        new Timer().schedule(new MyTimerTask(), 2000);
        
        
        while(true){
            try {
                System.out.println(new Date().getSeconds());
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        //quartz  周一~周五执行任务,周六日不执行
    }
}

 

Java多线程与并发库高级应用