文档章节

第一章:Java多线程技能

liululee
 liululee
发布于 2018/09/29 16:21
字数 1995
阅读 26
收藏 0

1.1进程和多线程的概念及线程的优点

进程:进程是操作系统结构的基础,是一次程序的执行,是一个程序及其数据在处理机上顺序执行时所发生的活动;是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。 线程:可以理解成是在进程中独立运行的子任务。 多线程的优点:同一时间内运行更多不同种类的任务,提高CPU利用率,是系统效率大大得到提升。

1.2使用多线程

一个进程在运行时至少有一个线程在运行。

1.2.1 继承Thread类

创建一个线程的方式有两种,一种是继承Thread类,一种是实现Runnable接口。使用Thread类时最大的局限就是不支持多继承,因为Java语言时单继承的。所以为了实现多线继承,完全可以实现Runnable接口,二者没有什么本质的区别。 Thread类结构

public class Thread implements Runnable {

}

Thread类实现了Runnable接口,它们之间具有多态关系。

public class MyThread extends Thread {
    @Override
    public void run(){
        super.run();
        System.out.println("MyThread is running!");
    }
}

1.2.2实现Runnable接口

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

Thread类也支持传入一个Ruunable接口的对象

public class Main {
    public static void main(String[] args) {
        MyRunnable thread = new MyRunnable();
        thread.run();

        Runnable runnable = new MyRunnable();
        Thread thread1 = new Thread(runnable);
        thread1.start();
    }
}

1.2.3实例变量与线程安全

自定义线程类中的实例变量针对其他线程可以有共享和不共享之分,这在多线程之间进行交互时是一个很重要的技术点。 (1)不共享数据的情况

public class MyThread extends Thread {
    private int count = 5;
    public MyThread (String name){
        super();
        this.setName(name);
    }

    @Override
    public void run() {
        super.run();
        while (count > 0){
            count--;
            System.out.println("由"+ this.currentThread().getName() + "计算, count=" + count);
        }
    }
}
public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread("A");
        MyThread thread1 = new MyThread("B");
        MyThread thread2 = new MyThread("C");
        thread.start();
        thread1.start();
        thread2.start();
    }
}

每个线程有各自的count变量,自己减少自己的count变量。这就是变量不共享。 (2)共享数据的情况

public class Section4Thread extends Thread {
    private int count = 5;

    @Override
    public void run() {
        super.run();
        System.out.println("由" + Thread.currentThread().getName() + "计算count:" + count);
        count--;
    }
}
public class Run {
    public static void main(String[] args) {
        Section4Thread thread = new Section4Thread();
        Thread a = new Thread(thread, "A");
        Thread b = new Thread(thread, "B");
        Thread c = new Thread(thread, "C");
        Thread d = new Thread(thread, "D");
        Thread e = new Thread(thread, "E");
        a.start();
        b.start();
        c.start();
        d.start();
        e.start();


    }
}

也可以用synchronized关键字来同步方法实现。

1.3 currentThread()方法

currentThread()方法返回当前代码段正在被哪个线程调用的信息。

1.4 isAlive()方法

isAlive()方法判断当前的线程是否处于活动状态。 Thread.currentThread 和 this的差异

public class Section5Thread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread.currentThread(): " + Thread.currentThread().getName() + Thread.currentThread().isAlive());
        System.out.println("this : "+this.getName() + this.isAlive() );
    }
}
public class Main {
    public static void main(String[] args) {
        Section5Thread t = new Section5Thread();
        Thread thread = new Thread(t);
        thread.setName("AAA");
        thread.start();
    }
}

1.5 sleep()方法

在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行),这个“正在执行的线程”指的是this.currentThread()返回的线程。 思考:线程的run()方法和start()方法的差别?

1.6 getId()方法

getId()方法的作用是取得线程的唯一标识。

1.7停止线程

停止一个线程意味着在线程处理完任务之前停掉正在做的操作,也就是放弃当前的操作。 介绍三种方式停止线程 1.使用退出标志,使线程正常退出,也就是当run方法完成后线程停止。 2.使用stop方法强行终止线程,但不推荐,以为stop()和suspend()及resume()一样,都是作废过期的方法,使用它们可能产生不可预料的后果。 3.使用Interrupt方法中断线程

1.7.1 停止不了的线程

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 50000; i++) {
            System.out.println("i = " + (i + 1));
        }
    }
}
public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        try {
            thread.start();
            Thread.sleep(2000);
            thread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

执行后,日志确实是5000行,线程并没有中断,也就是说调用interrupt()方法并没有中断线程。那如何停止线程呢?

1.7.2 判断线程是否是停止状态

this.interrupted():测试当前线程是否已经中断。---> 测试当前线程是否已经是中断状态,执行后具有将清除状态标志为false的功能。 ths.isInterrupted():测试线程是否已经中断。---> 测试线程Thread对象是否已经是中断状态,但不清楚状态标志。 总结:interrupted()告诉当前线程,执行完之后,就要被中断。isInterrupted()询问线程是否中断了?

1.7.3 能停止的线程——异常法

靠throw出InterruptException()然后捕获该异常来停止线程。

1.7.4 沉睡中停止

1.7.5-1.7.7 stop()暴力停止

直接调用stop()方法。这样会抛出ThreadDeath()异常,通常情况不需要显示捕捉。 stop()方法已经作废,如果强制让线程停止有可能会造成一些请理性工作得不到完成,以及对锁定的对象就行了“解锁”,导致数据得不到同步处理,出现数据不一致的情况。使用stop()方法释放锁将会给数据造成不一致的后果。

1.7.8 使用return停止线程

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

1.8 暂停线程

暂停线程意味着可以恢复运行,使用Thread.suspend()和Thread.resume()方法来是暂停和恢复线程。(注:这两方法都被标记为过期作废的方法,因此不推荐使用) 它们的缺点——独占,使用不当时,极易造成公共的同步对象的独占,使得其他线程无法访问公共的同步对象。

1.9 yield方法

yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间,但放弃时间不一定,有可能刚刚放弃,马上又获得CPU时间片。

1.10 线程的优先级

设置线程优先级使用setPriority()方法。在Java中,线程的优先级分为1~10这10个等级。如果大于10或者小于1,则JDK抛出异常throw new IllegalArgumengException()。 setPriority()方法源代码如下

public final void setPriority(int newPriority) {
	ThreadGroup g;
	checkAccess();
	if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY){
		throw new IllegalArgumentException();
	}
	if((g = getThreadGroup()) != null) {
		if(newPriority > g.getMaxPriority()){
			newPriority = g.getMaxPriority();
		}
		setPriority0(priority = newPriority);
	}
}

1.线程优先级的继承特性 A线程启动B线程,则B线程的优先级与A线程的优先级是一致的。 2.线程优先级的具有规则性 高优先级的线程总是大部分先执行完,但不代表高优先级的线程全部先执行完。也就是说线程的优先级具有一定的规则性的,CPU尽量将执行资源分配给优先级高的线程。 3.优先级具有随机性 优先级高的线程并不一定每一次都先执行完run()方法中的任务。

1.11 守护线程

Thread.setDaemon(true); //设置线程为守护线程。

当线程中存在非守护线程时,守护线程就存在。 概念: 只要当前JVM实例中存在任何一个非守护线程没有结束,守护线程就在工作,只有当最后一个非守护线程结束时,守护线程才随着JVM一同结束工作。它的作用就是为线程提供便利服务。守护线程最典型的应用就是GC(垃圾回收器)。

© 著作权归作者所有

liululee
粉丝 127
博文 66
码字总数 90743
作品 0
杭州
程序员
私信 提问
在JAVA私塾学习时整理的一套学习笔记(第一章)

JAVA基础 第一章Java入门 一. Java是什么? 一种计算机编程语言 一种软件开发平台 一种软件运行平台(JRE :java runtime environment) 一种软件部署环境 二. Java版本: Java标准版:JSE...

神码码
2011/10/11
204
0
Android--面试中遇到的问题总结(三)

《Android 开发工程师面试指南 LearningNotes 》,作者是陶程,由梁观全贡献部分。大家可以去知乎关注这两位用心的少年。这份指南包含了大部分Android开发的基础、进阶知识,不仅可以帮助准备...

sealin
2017/02/22
0
0
【Java学习路线】新手该如何一步步的学习 Java

新手该如何一步步的学习 Java? 如果真的想学Java,最好要循序渐进,有章有法的学习它! 今天小慕就不说一些学习方法和技巧了,直接来谈每个阶段要学习的内容。 首先,给大家分享一张以 企业...

Eddie_yang
2018/11/15
2.3K
0
淘宝(杭州)招聘架构师和资深JAVA开发

淘宝网(www.taobao.com)是中国领先亚洲最大的个人电子商务交易平台,2003年7月由全球最佳B2B网站阿里巴巴投资人民币4.5亿元创办。在全球权威ALEXA排名中,淘宝网全球网站综合排名位居第14名...

sirch
2010/06/08
1K
4
【北京】大型互联网公司招聘高级java开发工程师(结算&财务系统)【猎头招聘】

高级java开发工程师(结算&财务系统) 一淘-广告技术 北京 工作年限 3年以上 学历要求 本科 岗位描述 1. 和产品经理一起讨论需求,并对需求进行分析、设计和开发工作; 2. 核心代码编写、指导...

melody123
2012/05/15
812
4

没有更多内容

加载失败,请刷新页面

加载更多

浅谈prototype原型模式

一、原型模式简介 原型(Prototype)模式是一种对象创建型模式,他采取复制原型对象的方法来创建对象的实例。使用原型模式创建的实例,具有与原型一样的数据。 原型模式的特点: 1、由原型对...

青衣霓裳
12分钟前
2
0
shell mysql 备份

#!/bin/bash time2=$(date "+%Y-%m-%d-%H:%M:%S") /usr/local/mysql/bin/mysqldump -uroot -p ad > /usr/local/mysql/backup/"$time2".sql 变量引用原来是这么用的。......

奋斗的小牛
20分钟前
3
0
Jmeter监控Linux服务器操作

系统:Win7 64位 工具:Jmeter 4.0 要准备好的插件:JMeterPlugins-Standard-1.4.0,ServerAgent-2.2.1 解压JMeterPlugins-Standard-1.4.0.zip,将其中\lib\ext\JMeterPlugins-Standard.jar......

魔鬼妹子
20分钟前
4
0
系列文章:云原生Kubernetes日志落地方案

在Logging这块做了几年,最近1年来越来越多的同学来咨询如何为Kubernetes构建一个日志系统或者是来求助在这过程中遇到一系列问题如何解决,授人以鱼不如授人以渔,于是想把我们这些年积累的经...

Mr_zebra
21分钟前
3
0
入门必备!快速学会用Aspose.Words在表格中插入和删除列!

Aspose.Words For .Net(点击下载)是一种高级Word文档处理API,用于执行各种文档管理和操作任务。API支持生成,修改,转换,呈现和打印文档,而无需在跨平台应用程序中直接使用Microsoft W...

mnrssj
26分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部