Java多线程编程核心技术的笔记之1

Java  2018年5月27日 pm3:34发布7年前 (2018)更新 91es.com站长
380 0 0

1、什么是进程,线程和多线程

1. 进程

在百度百科中的定义是

进程(process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.程序是指令,数据以及组织形式的描述,进程是程序的实体.

我们可以把win系统中运行的一个exe程序看做一个进程,Android中可以把一个应用看做一个进程.

2.线程

在百度百科中的定义是

线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。

线程可以理解为在进程中独立运行的子任务.比如腾讯QQ.exe运行时,有很多子任务在执行,文件传输任务,视频直播任务,文档下载任务等.这些子任务都是线程.

PS:多线程是异步的,线程被调用是随机的.

3. 多线程

在百度百科中的定义是

多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。

好处:提供执行效率或性能

多线程就是我们在用QQ聊天时,可以一边下载文件,一遍视频直播等"同时"操作.

2、线程的实现和启动

1.继承Thread


    //匿名启动
    new MyThread().start();

    //
    MyThread myThread = new MyThread();
    //不能调用多次
    myThread.start();


    private class MyThread extends Thread {
        @Override
        public void run() {
            super.run();
        }
    }

PS:一个线程变量不能多次调用start(),否则会出现:Exception in thread "main" java.lang.IlleaglThreadStateException异常.

2.实现Runnable接口

    //通过Thread启动
    Thread thread= new Thread(new MyRunnable());
    thread.start();

    //实现Runnable接口
    private class MyRunnable implements Runnable{

        @Override
        public void run() {

        }
    }

由于Java是单继承,不允许多继承,因此继承Thread有一定的局限性,推荐大家使用第二种方式

3、什么是非线程安全

非线程安全主要是指:多个线程对同一个对象中的同一个实例变量进行操作时会出现值被更改和值不同步的情况,进而影响程序执行流程.

解决发生非线程安全问题的方法就是使用同步方法等同步手段

4、线程中的一些方法

1. start()

启动线程,但此时线程只是处于就绪状态,并没有执行.至于什么时候执行需要看CPU.

2. currentThread()

返回当前代码是在哪个线程中调用.

3.isAlive()

判断当前线程是否处于线程已经启动且尚未终止的活动状态

4. sleep()

指定休眠一段时间,但此时不会释放锁,休眠后继续运行.

5. getId()

获取线程的唯一标识ID

6. interrupt()

在当前线程中设置一个中断标志,并不会直接中断线程.

7.interrupted()

测试当前线程是否中断状态,执行后同时将状态标志设置为false

8. isInterrupted()

判断线程Thread对象是否是中断状态,但不清除状态标志.

9. yield()

放弃当前的CPU资源,将它让给其他的任务占用CPU资源,当放弃的时间不确定,有可能当放弃,又重新获取CPU时间.

5、停止线程

停止线程单独提出了,因为这有些'麻烦'

一下三种可以终止正在运行的线程:

1. 使用退出标志,使线程正常退出.也就是当run()方法完成后线程终止

2. 使用stop()方法强行终止线程,,,但stop()方法已经废弃,不推荐使用

3. 使用interrup()方法中断线程.

方法1:使用线程中断标志判断线程是否退出状态

从上面第4部分我们知道.interrupt()方法是中断线程的,但又不是真真的"中断",只是把线程中断标志设置位true.

            //中断当前线程
             Thread.currentThread().interrupt();

            //获取中断标志位
            Log.d(TAG, "---1--interrupted:"+ Thread.interrupted()); //true
            Log.d(TAG, "---2--interrupted:"+ Thread.interrupted()); //false
        MyThread myThread = new MyThread();
        myThread.start();
        //中断myThread线程
        myThread.interrupt();
        Log.d(TAG, "---1--interrupted:" + myThread.isInterrupted()); //true
        Log.d(TAG, "---2--interrupted:" + myThread.isInterrupted()); //true

我们可以通过线程的静态方法interrupted()方法获取当前线程的中断标志并返回,但我们要记住,interrupted()方法调用后会把中断标志清除并设置为false

而非静态方法isInterrupted()方法返回调用的线程是否中断,调用后也不会把中断状态清除.

因此我们可以在线程中,如果需要退出,通过判断中断标志然后退出

        try {
            //线程的启动
            MyThread myThread = new MyThread();
            myThread.start();

            //延迟2s
            Thread.sleep(2000);

            //myThread设置中断
            myThread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    //定义一个线程
    private class MyThread extends Thread {
        @Override
        public void run() {
            super.run();
            try {
                Log.d(TAG, "-------for---start------");
                for (int i = 0; i < 10; i++) {
                    Log.d(TAG, "------current i:" + i);
                    Thread.sleep(1000);
                    if(this.interrupted()){
                        //如果有中断(true),抛出中InterruptedException
                        throw new InterruptedException();
                    }
                }
                Log.d(TAG, "-------for---end------");
            } catch (InterruptedException e) {
                Log.d(TAG, "-----catch" +
                        "" +
                        "-InterruptedException------");
                e.printStackTrace();
            }

            Log.d(TAG, "-------run---end------");
        }
    }

打印日志

-------for---start------
------current i:0
------current i:1
-----catch-InterruptedException------
-------run---end------

......

后续整理,这部分有些不太懂.....谢谢理解

6、线程的优先级

在操作系统中,线程是划分优先级的.优先级高的线程得到的CPU资源最多,也就是CPU优先执行优先级高的线程对象.

在Java中,线程的优先级划分为1~10个等级,如果大于10或者小于0,JDK会抛出异常throw new IllegalArgumentException

Java中定义了三个优先级常量:

public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;

在Java中,线程的优先级是具有继承性的和随机性的.线程A中启动线程B,那么线程A和线程B的优先级都是一样的.如果线程C的优先级比线程D高,但执行结果并不是一定先执行玩C再执行D的.

PS:优先级高的线程并不是一定先执行完,而是CUP尽可能的把资源让给优先级高的线程对象.

7、守护线程

Java中有两种线程,一种是用户线程,另一种是守护线程.

守护线程就是一种特殊的线程,它具有陪伴的特性.

当进程中没有用户进程时候,守护线程就会自动销毁.

典型的守护线程有垃圾回收线程.如果用户线程不存在,垃圾线程也就没必须要存在,所以会自动销毁.

 历史上的今天

  1. 2023: Android批量拷贝文件(0条评论)
  2. 2022: [NDK开发]Android JNI 开发之静态注册(0条评论)
  3. 2021: [代码片段]通过pinyin4j实现汉字转拼音(0条评论)
版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

李月亮:那些你所不知道的大事

在你的生命里,经历了一些很重大的事情,可是你并不知道。5岁那年,爸爸下班回来,你跑去迎接他,不小心摔了个狗啃泥,不过没有受伤。你并不知道,就在你摔倒的地方往左两厘米,立着一根小钉子,如果你稍微偏一偏,左眼就失明了。10岁那年,你一个人在家煮方便面,刚把水壶放到煤气炉上,就接到妈妈的电话让你去姥...

[摘]svc命令:管理电源控制,无线数据,WIFI

本文摘抄于《Android命令行测试BT,WIFI,Sensor工作状态》svc命令,位置在/system/bin目录下,用来管理电源控制,无线数据,WIFI。[plain] view plaincopy# svc svc Available commands: ...

茅盾:白杨礼赞

白杨树实在是不平凡的,我赞美白杨树!当汽车在望不到边际的高原上奔驰,扑入你的视野的,是黄绿错综的一条大毡子;黄的,那是土,未开垦的处女土,几十万年前由伟大的自然力所堆积成功的黄土高原的外壳;绿的呢,是人类劳力战胜自然的成果,是麦田,和风吹送,翻起了一轮一轮的绿波——,这时你会真心佩服昔人所造的两个...

王小波:卡尔维诺与未来的一千年

朋友寄来一本书,卡尔维诺的《未来千年备忘录》,我正在看着。这本书是他的讲演稿,还没来得及讲,稿也没写完,人就死了。这些讲演稿分别冠以如下题目:轻逸、迅速、易见、确切和繁复。还有一篇"连贯",没有动笔写,所以我整天在捉摸他到底会写些什么,什么叫做"连贯"。卡尔维诺指出,在未来的一千年里,文学会继续繁荣...

朱自清:背影

那年冬天,祖母死了,父亲的差使也交卸了,正是祸不单行的日子。我从北京到徐州打算跟着父亲奔丧回家。到徐州见着父亲,看见满院狼藉的东西,又想起祖母,不禁簌簌地流下眼泪。父亲说:“事已如此,不必难过,好在天无绝人之路!”回家变卖典质,父亲还了亏空;又借钱办了丧事。这些日子,家中光景很是惨淡,一半为了丧事...

SharedPreferences最后一次写入时断电偶尔存在不保存问题

前言最近测试反馈,播放音乐的信息断电时偶尔不记忆。项目中的记忆是使用sharedpreferences的,sharedpreferences是以xml文件保存,保存的位置在:/data/data/[包名]/shared_prefs测试反馈的关键字[断电]、[偶尔]和[不记忆],也就是说这...