课程咨询 :13486356750 QQ:1079585464

厦门达内java培训

  • 达内:Java多线程基础知识

    发布:厦门Java培训      来源:PHPERZ      时间:2015-12-24


  •     厦门达内Java培训专家介绍Java多线程基础知识,促进达内Java培训班学员更好的学习Java开发。

        线程的定义:进程是从系统获取资源的最小单位,线程是程序执行的最小单位。程序是静态存在于磁盘上的一段文本,进程运行这段文本记录的命令。

        因此,进程从系统那里获取到了一定的CPU占用时间片、内存单元和IO等等资源,然后线程将这些资源利用起来执行程序。线程执行程序是什么?就是把程序记录的那些命令逐条依序一步步在CPU上运作,数据在内存、IO上流转,将命令执行完。

        一、创建线程的方法

        1.创建直接创建Thread的子类,重写run()方法;

    class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("This is my thread");
        }
    }

    public class Test {
        public static void main(String[] args) {
            MyThread thread = new MyThread();
            thread.start();
        }
    }

        2.创建一个线程执行类实现Runnable接口,在这个执行类里实现Runnable的run()方法,创建该执行类的对象后,用此执行类对象初始化新线程,启动新线程时即执行这个执行对象的run()方法;

    class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("This is my thread");
        }
    }

    public class Test {
        public static void main(String[] args) {
            Thread thread = new Thread(new MyRunnable());
            thread.start();
        }
    }

        3.通过线程工厂用工厂模式来创建新线程,新建工厂类继承ThreadFactory类重写newThread()方法,通过指定实现了Runnable接口的执行类来创建与之对应的线程;

    public class ThreadFactoryDemo {

        public static void main(String[] args) {
            ThreadFactory factory = new ThreadFactory() {

                @Override
                public Thread newThread(Runnable r) {
                    // TODO Auto-generated method stub
                    return new Thread(r);
                }
            };
            factory.newThread(new Runnable() {

                @Override
                public void run() {
                    System.out.println("in runnable.");

                }
            }).start();
        }

    }

        提示一下,只有调用Thread类的Start方法,才能真正地在一个独立的线程中执行代码,直接调用Thread类的run方法,并不能启动一个新的线程,代码是在调用者线程中执行的。

        那么主线程的run()方法在哪里呢?任何java程序的main执行入口担当着启动主线程的作用,只要进入了main函数就执行了主线程,因此整个main函数里的内容就是主线程的run()方法。

        二、线程究竟执行哪个run()方法 ?

        当线程同时具有可执行对象实现的run()方法和线程重写的run()方法时,启动线程时究竟执行哪个run()方法呢?

        结果是:如果只定义了可执行对象的run()方法则执行这个run()方法,如果只重写了线程的run()方法则执行这个run()方法,如果两个方法都有则执行线程重写的run()方法。

    public class Test {
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {

                @Override
                public void run() {
                    System.out.println("Runnable.run()");

                }
            }) {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    System.out.println("Thread.run()");
                }
            };
            thread.start();
        }
    }

        三、线程的休眠

        使用Thread类的sleep()方法或者使用TimeUnit的相关方法来休眠线程,休眠的意思是资源仍被占用,但是线程保留原来的状态没有活动;

    public class ThreadSleep {
        public static void main(String[] args) {
            Thread th = new Thread(new Runnable() {
                public void run() {
                    for (int i = 0; i < 10; i++) {
                        try {
                            // Thread.sleep(500);
                            TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            });
            th.start();
        }
    }

        四、线程中断

        线程中断的意思是线程停止当前的运行状态让出资源结束生命周期,当外界想要一个线程中断时需要调用它的interrupted()方法,调用后不是直接就可以中断这个线程,而是将线程的interrupted标记位赋为1,如果要线程要响应这个中断则定期需要检查这个标记,检查到被中断标记后自己退出执行状态。

    public class ThreadInterruptDemo {
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread() {
                @Override
                public void run() {
                    while (true) {
                        System.out.println("running");
                        if (isInterrupted())
                            return;
                    }
                }
            };
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        }
    }

        五、线程定时任务

        线程要实现定时任务的话可以使用Runnable的实现类TimerTask,此类需要重写run()方法以完成具体需要进行的定时任务。然后由定时器Timer来调度,使用Timer的schedle()方法相当于启动这个定时任务线程。

    public class TimerTaskDemo {
        public static void main(String[] args) {

            TimerTask task = new TimerTask() {
                private int counter = 0;

                @Override
                public void run() {
                    System.out.println(counter + ":invoked!");
                    counter++;
                }
            };
            Timer timer = new Timer();
            // 过2秒钟后首次运行,以后每隔3秒运行一次
            timer.schedule(task, 2000, 3000);
        }
    }

        六、线程运行过程中的异常处理

        线程的run()方法中是不允许直接抛出异常的,也就是说不能有这样的写法:run() throws Exception ,原因在于在线程的运行过程中应该最大限度地保持正常工作,因此除了一些不可预知的运行时异常,不应该主动抛出受控异常。如果非要在run()方法里处理抛出的异常,则应该定义一个实现了UncaughtExceptionHandler的类,然后指定这个类的对象在重写的uncaughtException()方法里去处理抛出的异常。另外一种方法是,将这个线程加入一个线程组,在线程组里重写uncaughtException()方法来处理抛出的异常,这时线程组的作用相当于实现了UncaughtExceptionHandler的类。

        1.使用handler对象处理异常:

    public class ThreadTest {
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    throw new RuntimeException("格式错误");
                }
            });
            thread.setUncaughtExceptionHandler(new MyHandler());
            thread.start();
        }
    }

    class MyHandler implements UncaughtExceptionHandler {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println(t.getName() + ":" + e.getMessage());

        }
    }

        2.使用线程组处理异常:

    public class ThreadGroupDemo {
        public static void main(String[] args) {
            ThreadGroup threadGroup1 = new ThreadGroup("group1") { 
                public void uncaughtException(Thread t, Throwable e) {
                    System.out.println(t.getName() + ": " + e.getMessage());
                }
            };
            Thread thread1 = new Thread(threadGroup1, new Runnable() {
                public void run() {
                    throw new RuntimeException("测试异常");
                }
            });

            thread1.start();
        }
    }



上一篇:达内:40个常见的Java多线程问题

下一篇:达内解读Java Executor 框架

最新开班日期  |  更多

Java--大数据周末班

Java--大数据周末班

开班日期:每周一

Java--大数据全日制班

Java--大数据全日制班

开班日期:每周一

Java--零基础周末班

Java--零基础周末班

开班日期:每周一

Java--零基础全日制班

Java--零基础全日制班

开班日期:每周一

  • 地址:厦门软件园二期望海路59号之一401达内科技
  • 课程培训电话:13486356750 QQ:1079585464     全国服务监督电话:400-111-8989
  • 服务邮箱 tousu@tedu.cn
  • 2001-2016 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56