`
HotStrong
  • 浏览: 507572 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Java线程编程基础 第一章

阅读更多

 

 

Java线程编程基础 第一章

 

1、本章任务:建立多线程程序

2、本章知识点:

  •   了解Java线程模型
  •   掌握创建线程的方法
  •   设置线程优先级


3、多线程编程概述

  •   Java提供了对多线程编程的内置支持
  •   多线程程序包括能够并发运行的两个或多个代码段

      单线程、多线程对比示例图:

 

       
    从图中可以看出:
    1.单线程中的3段代码只能在不同的时间点执行,
    2.多线程中的3段代码可以在同一时间点执行

4、进程与线程

  • 进程:一个进程是 一个正在执行的程序 ,目前的操作系统大多都支持同时运行两个或多个程序,称为多任务操作系统
  • 线程:单个程序 可以同时执行 两个或更多的任务 ,每个任务称 一个线程 ,进程包含线程
  • 进程是重量级的任务 ,每个进程都有自己独立的地址空间
  • 线程是轻量级的任务 ,他们共享一个地址空间,共享同一个进程
  • 进程间通信代价昂贵而且受限,线程通信很容易
  • 利用多线程可使你的程序最大限度地利用CPU,因为空闲时间被限制在最小


5、
Thread类和Runnable接口

    Java的多线程系统构建在Thread类 、方法以及Runnable接口 之上。
    可以通过继承Thread类或者实现Runnable接口创建一个新线程
   
    Thread类定义了几个管理线程的方法,常用方法如下:
    方法名            功能
    ====================================
    getName        获取线程名
    getPriority      获得线程的优先级
    isAlive            判定线程是否仍在运行
    join                等待一个线程终止
    run                线程入口方法
    sleep             暂停一个线程一段时间
    start              启动线程

6、程序的主线程


    6.1)主线程描述
    Java程序启动时 (从main方法开始),一个线程 立刻开始运行,这个线程称
    为主线程 ,主线程的重要性体现在如下两个方面:
        1)它是产生其他子线程的线程
        2)一般情况下,必须是最后一个结束 执行的线程,
             因为它要执行各种关闭操作


    主线程不但在程序开始时自动创建,也能通过Thread对象来控制,此时需要
    调用:Thread.currentThread()

    6.2)主线程控制示例代码
   

public static void main(String args[ ]){
        Thread t = Thread.currentThread( ); //获取当前线程(主线程)
        System.out.println("当前线程:" + t); //输出:线程名-优先级-线程组名
        //改变主线程名称
        t.setName("My Thread");         System.out.println("改变之后的名称:" + t);

        //打印数字1 ~ 5,每隔1秒打印1次
        try{
            for(int i = 1; i <= 5; i++){
                System.out.println(i);
                Thread.sleep(1000); //休眠1000毫秒
            }
        }catch(InterruptedException e){
             System.out.println( " 主线程中断! " );
        }
    }

 

7、创建线程

    Java定义了两种 创建线程的方法
    1)可以实现Runnable接口 ,这是创建线程最简单的方法,实现Runnable接口
         只需一个简单的run()方法,其声明如下:
        public void run();
         run()方法是线程的进入点,线程在run方法返回时结束
   
    2)可以继承Thread类 ,重写Thread类的run()方法

8、创建线程
方法1:实现Runnable接口

/**
     * 线程类MyThread,实现Runnable接口
     */
    public class MyThread implements Runnable{ //线程类
        //线程入口点
        public void run(){
            try{
                //打印数字1 ~ 5,每隔500毫秒打印一次
                for(int i = 1; i  <= 5; i++){
                    System.out.println("子线程打印:" + i);
                    Thread.sleep(500); //休眠500毫秒
                }
            }catch(InterruptedException e){
                 System.out.println("子线程中断!");
            }
            System.out.println("子线程执行结束!");
        }
    }
   
    /**
     * 线程类MyThread的测试类
     */
    public class TestMyThread{
        public static void main(String args[ ]){
            //创建线程
            Thread t = new Thread(new MyThread(), "Demo Thread");
            System.out.println("子线程被创建:" + t); //显示线程信息
            t.start(); //启动线程
            //主线程中间隔1秒,打印数字1 ~ 5
            try{
                for(int i = 1; i  <= 5; i++){
                    System.out.println("主线程打印:" + i);
                    Thread.sleep(1000); //休眠1000毫秒
                }
            }catch(InterruptedException e){
                    System.out.println("主线程中断!");
            }
            System.out.println("主线程执行结束!");
        }
    }

 

9、创建线程 方法2:继承Thread类

   

/**
     * 线程类MyThread1,继承Thread类
     */
    public class MyThread1 extends Thread{
        public MyThread1(){
            super("Demo Thread"); //线程命名
        }
        //重写线程入口方法
        public void run(){
            try{
                //打印数字1 ~ 5,每隔500毫秒打印一次
                for(int i = 1; i  <= 5; i++){
                    System.out.println("子线程打印:" + i);
                    Thread.sleep(500); //休眠500毫秒
                }
            }catch(InterruptedException e){
                 System.out.println("子线程中断!");
            }
            System.out.println("子线程执行结束!");
        }
    }
   
    /**
     * 线程类MyThread1的测试类
     */
    public class TestMyThread1{
        public static void main(String args[ ]){
            //创建线程
            Thread t = new MyThread1();
            System.out.println("子线程被创建:" + t); //显示线程信息
            t.start(); //启动线程
            //主线程中间隔1秒,打印数字1 ~ 5
            try{
                for(int i = 1; i  <= 5; i++){
                    System.out.println("主线程打印:" + i);
                    Thread.sleep(1000); //休眠1000毫秒
                }
            }catch(InterruptedException e){
                System.out.println("主线程中断!");
            }
            System.out.println("主线程执行结束!");
        }
    }

 


10、如何选择创建线程的方式

    问: Java有两种创建线程的方式,哪种更好?
   
    1. Thread类定义了多个派生类可以重写的方法,run()方法只是其中之一,
    所以只有在需要增强或者修改Thread类时才应该使用继承Thread类方式
   
    2. 如果不想重写Thread类的run()方法外的其他方法,最好还是简单的
    实现Runnable接口(推荐)

11、线程的状态

  • 准备运行状态:ready to run
  • 运行状态:running
  • 暂停状态:suspended 运行中的线程可以暂停,暂停的线程可以重新启动
  • 阻塞状态:blocked 线程在等待其他资源时被阻塞

    (这个状态和视频播放器的操作非常类似,: )
   
    注意:线程在任何时候都能被终止,一旦终止就不能被重新激活
   
12、启动多个线程

   

/**
     * 改进的MyThread线程类(改为自启动线程)
     */
    public class MyThread implements Runnable {
       
        private Thread t;//线程对象
        public Thread getT() {
            return t;
        }
        /**构造方法*/
        public MyThread(String threadName){           
            //创建线程对象
            this.t = new Thread(this, threadName);
            System.out.println("创建子线程:" + threadName);
            //启动线程
            this.t.start();
        }
       
        /**
         * 功能:线程入口方法
         */
        public void run() {
           
            Thread t = Thread.currentThread();
            try {
               
                //打印数字1 ~ 5,间隔1秒
                for(int i = 1; i <= 5; i++){
                    System.out.println(t.getName() + " 打印:" + i);
                    //休眠1秒
                    Thread.sleep(1000);
                }               
            } catch (InterruptedException e) {
                System.out.println("子线程中断!");
            }
           
            System.out.println("子线程结束!");           
        }
    }
   
    /**
     * 多线程测试类
     */
    public class TestMyThread {
        public static void main(String[] args) {
           
            //创建线程对象1
            MyThread t1 = new MyThread("子线程1");
           
            //创建线程对象2
            MyThread t2 = new MyThread("子线程2");
           
            try {               
                //主线程打印数字1 ~ 5,间隔1秒
                for(int i = 1; i <= 5; i++){
                    System.out.println("主线程打印:" + i);
                    //休眠1秒
                    Thread.sleep(1000);
                }
               
            } catch (InterruptedException e) {
                System.out.println("主线程中断!");
            }           
            System.out.println("主线程结束!");
        }
    }

 

13、使用isAlive()join()

    问题: 主线程一般要最后结束,之前的示例中是通过在main方法中加入sleep()
    使主线程休眠足够长的时间以确保主线程最后结束,这个解决方式合理吗?怎样
    才能知道子线程是否终止?或者说怎样才能保证主线程最后结束?

    答案: 有两种方式可以确定一个线程是否结束:
    1)在线程中调用isAlive(),这个方法由Thread定义,如果它调用的线程仍在运行,
         返回true,否则返回false
    2)使用join()方法来等待另一个线程的结束,该方法一直等待直到它调用的线程终止

14、isAlive()和jion()示例

    尝试运行以下代码并观察主线程是否最后结束:

   

public static void main(String[] args) {
        MyThread t1 = new MyThread("子线程1"); // 创建线程1
        MyThread t2 = new MyThread("子线程2"); // 创建线程2
        MyThread t3 = new MyThread("子线程3"); // 创建线程3

            //显示线程是否运行
        System.out.println("子线程1是否运行:" + t1.getT().isAlive());
        System.out.println("子线程2是否运行:" + t2.getT().isAlive());
        System.out.println("子线程3是否运行:" + t3.getT().isAlive());
        // 主线程等待子线程结束
        try {
            System.out.println("等待子线程结束…");
            t1.getT().join(); // 等待t1线程结束
            t2.getT().join(); // 等待t2线程结束
            t3.getT().join(); // 等待t3线程结束
        } catch (InterruptedException e) {
            System.out.println("主线程中断!");
        }
        //显示线程是否运行
        System.out.println("子线程1是否运行:" + t1.getT().isAlive());
        System.out.println("子线程2是否运行:" + t2.getT().isAlive());
        System.out.println("子线程3是否运行:" + t3.getT().isAlive());
        System.out.println("主线程执行结束!");
    }

 


15、线程优先级概述

    Java给每个线程分配一个优先级,以决定哪个线程可以优先分配CPU时间
    优先级是一个整数,用于指定线程的相对优先程度
    优先级可以决定什么时候从一个运行中的线程切换到另一个线程,切换规则如下:

  •   一个线程自愿释放控制(放弃、睡眠或者阻塞),所有其他线
      程被检查,高优先级线程被分配CPU时间
  •   一个线程可以被另一个高优先级线程抢占资源,称为抢占式多任务

    注意:具有同一优先级的线程竞争CPU时间,不同操作系统的处理方式上存在差别

16、线程优先级设置

  • 线程调度器使用线程优先级以决定什么时候允许运行
  • 理论上高优先级的线程将比低优先级的线程得到更多CPU时间
  • 低优先级线程在运行时,高优先级的线程会抢占低优先级线程的执行权
  • 设置线程优先级,使用setPriority()方法:

    final void setPriority(int level);
    参数level为线程的优先级 ,其值在1 ~ 10 之间


    Thread类提供了如下常量方便优先级的设置
    Thread.MIN_PRIORITY == 1
    Thread.MAX_PRIORITY == 10
    Thread.NORM_PRIORITY == 5


17、线程优先级示例

   

/**
     * 功能:计数器线程
     */
    public class Clicker implements Runnable {
       
        private int click = 0;//计数值        
        private Thread t;//线程对象        
        private volatile boolean running = true;//运行开关
       
        public int getClick() {
            return click;
        }       
        public Thread getT() {
            return t;
        }       
        /**构造方法,参数为优先级*/
        public Clicker(int priority){
            this.t = new Thread(this);
            this.t.setPriority(priority);//设置线程优先级
        }
       
        public void run() {           
            while(this.running){               
                this.click++;//计数器累加
            }
        }
       
        public void start(){
            this.t.start();//启动线程
        }       
        public void stop(){
            this.running = false;//结束线程
        }       
    }
   
    /**
     * 计数器线程测试类
     */
    public class TestClicker {
        public static void main(String[] args) {
          
            //创建线程,设置4种档次的优先级
            Clicker hi = new Clicker(Thread.NORM_PRIORITY + 2);
            Clicker hi1 = new Clicker(Thread.NORM_PRIORITY + 4);
            Clicker lo = new Clicker(Thread.NORM_PRIORITY - 2);
            Clicker lo1 = new Clicker(Thread.NORM_PRIORITY - 4);           
            //启动线程
            hi.start();
            hi1.start();
            lo.start();
            lo1.start();
           
            try {               
                Thread.sleep(2000);//休眠2秒                
                //结束线程
                hi.stop();
                hi1.stop();
                lo.stop();
                lo1.stop();
                //等待线程结束
                hi.getT().join();
                hi1.getT().join();
                lo.getT().join();
                lo1.getT().join();               
            } catch (InterruptedException e) {
                System.out.println("主线程中断!");
            }           
            //显示计数器值
            System.out.println("lo1计数器:" + lo1.getClick());
            System.out.println("lo计数器:" + lo.getClick());
            System.out.println("hi计数器:" + hi.getClick());
            System.out.println("hi1计数器:" + hi1.getClick());
            System.out.println("主线程结束!");           
        }
    }

 

18、总结

  • 进程与线程的区别?
  • 如何获取主线程?
  • 创建线程的两种方式?
  • 获知线程是否运行使用哪个方法?
  • 等待线程执行结束使用哪个方法?
  • 线程优先级的范围是什么?

 

 

 

3
1
分享到:
评论

相关推荐

    完整版java基础入门教程由浅入深讲解 Java语言编程基础 含辅助PPT资料 全套PPT课件 共15个章节.rar

    完整版java基础入门教程由浅入深讲解 Java语言编程基础 第13章 多线程(共50页).ppt 完整版java基础入门教程由浅入深讲解 Java语言编程基础 第14章 网络通信(共76页).ppt 完整版java基础入门教程由浅入深讲解 ...

    线程 JAVA java线程 java线程第3版 java线程第2版第3版合集

    电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关...第五章 Java线程编程的例子 第六章 Java线程调度 第七章 Java线程调度例子 第八章 和同步相关的高级主题 第九章 多处理器机器上的并行化 第十章 线程组

    Java程序设计案例教程-第8章-多线程编程.pptx

    第8章 多线程编程 第1页 本章概述 本章的学习目标 主要内容 Java程序设计案例教程-第8章-多线程编程全文共36页,当前为第1页。 本章概述 前面我们所开发的程序大多是单线程的,即一个程序只有一条从头到尾的执行路线...

    java 多线程设计模式 进程详解

    第一章 线程简介 Java术语 线程概述 为什么要使用线程? 总结 第二章 Java线程API 通过Thread类创建线程 使用Runable接口的线程 线程的生命周期 线程命名 访问线程 线程的启动、停止和连接 总结 第三章 同步技术...

    Java语言程序设计(理论基础部分)ppt

    1 第一章 Java语言概述(1) 2 第一章 Java语言概述(2) 3 第二章 Java基础 4 第三章 面向对象程序设计基础 5 第四章 图形用户界面设计 6 第五章 Java Swing基础 7 第六章 Java图形与图像处理 8 第七章 多线程与...

    JAVA语言程序基础教程

    第一章 Java语言的基础知识 第二章 面向对象的编程 第三章 Java程序的执行 第四章 标识符、关键字与类型 第五章 运算符、表达式与数组 第六章 Java语句 第七章 面向对象编程介绍 第八章 接口 第九章 Java包与...

    Java基础课堂笔记

    Java基础笔记, 第一章:编程基础 第二章:数组 第三章:面向对象程序开发 第四章:异常机制 第五章:多线程技术 第六章:常用类API 第七章:集合框架(容器)+其他类对象使用 第八章:IO流 第九章:GUI编程 第十章...

    Java并发编程实战

    第一部分 基础知识 第2章 线程安全性 2.1 什么是线程安全性 2.2 原子性 2.2.1 竞态条件 2.2.2 示例:延迟初始化中的竞态条件 2.2.3 复合操作 2.3 加锁机制 2.3.1 内置锁 2.3.2 重入 2.4 用锁来保护状态 ...

    JAVA程序设计基础

    第一章 计算机语言概述 第二章 Java的开发环境 第三章 Java语言基础 第四章 Java面向对象的程序设计 第五章 异常处理 第六章 Java的可重用类 第七章 Java小应用程序Applet 第八章 用户界面 第九章 Java的多线程...

    java网络编程第四版pdf

    java网络编程第四版PDF,带目录和书签。 第一章 基本网络概念 第二章 流 第三章 线程 ...

    《Java并发编程的艺术》源代码

    Java线程之间的通信对程序员完全透明,内存可见性问题很容易困扰Java程序员,本章试图揭开Java内存模型的神秘面纱。 第4章从介绍多线程技术带来的好处开始,讲述了如何启动和终止线程以及线程的状态,详细阐述了多...

    java 核心编程 java

    全书共14章,包括Java基本的程序结构、对象与类、继承、接口与内部类、图形程序设计、事件处理、Swing用户界面组件、部署应用程序和Applet、异常日志断言和调试、泛型程序设计、集合以及多线程等内容。. 全书对Java...

    java学习课件,网络编程语言

    第一章 java 简介; 第二章 java 语言基础(1); 第二章java语言基础(2); 第三章 面向对象编程的基本概念; 第四章 java 中的对象、类、包和接口; 第五章 异常处理; 第六章 编写文本应用程序; 第七章 线程; ...

    java线程实战手册

    java并发编程实战手册,不过只有第一章,如果要的话以后我再上传全部的

    JAVA2核心技术(第二版中文PDF).part2.rar

    第一章 java简介 第二章 java编程环境 第三章 java基本编程结构 第四章 对象与类 第五章 进一步介绍OOP:继承 第六章 用AWT进行图形程序设计 第七章 用AWT设计用户界面 第八章 小应用程序 第九章 数据结构 第十章 ...

    JAVA2核心技术(第二版中文PDF).part1.rar

    第一章 java简介 第二章 java编程环境 第三章 java基本编程结构 第四章 对象与类 第五章 进一步介绍OOP:继承 第六章 用AWT进行图形程序设计 第七章 用AWT设计用户界面 第八章 小应用程序 第九章 数据结构 第十章 ...

    java编程基础,应用与实例

    1.5 运行第一个Java程序 7 1.6 巩固练习 8 第2章 理解对象与类 9 2.1 什么是对象 9 2.2 什么是类 9 2.3 HelloJava示例的分析 11 2.4 巩固练习 12 第3章 Java语言的基本语法 13 3.1 代码编写规则...

    编程实践:Java进阶100例

    第一章:Java入门; 第二章:MyEclipse的基本使用; 第三章:Java基础语法; 第四章:数组的应用; 第五章:面向对象的Java编辑; 第六章:接口与内部类; 第七章:集合的应用; 第八章:异常和反射; 第九章:初识...

Global site tag (gtag.js) - Google Analytics