初识多线程

多线程对于有一定开发经验的程序员来说肯定不会陌生,不过相信很多人跟我一样,平时其实没有那么多的多线程实例去做,即使有可以直接使用spring来实现简单的使用,更多的是在面试中,一般都会涉及,特别是大公司的面试。

在阿里的初面中,我就被刷下来,失落感是显而易见的,虽然面试官也坦诚,如果我去了阿里也是做应用,面试问的这些东西也不会有太多涉及,面试门槛高,所以为了去大公司也得耐心的了解。当然面试官也说了,如果你知道这些偏僻的内容,对工作某个点是有用的,我同意这个说法。

所以,对于多线程这部分耐心看下来,对于找工作或者技术提升都是有用的。与君共勉!

文章借鉴于《Java多线程编程实战指南(设计模式篇)》 黄文海/著,以及极客学院多线程视频http://search.jikexueyuan.com/course/?q=%E5%A4%9A%E7%BA%BF%E7%A8%8B。

一,为什么要有多线程?

多线程的前提是各种设备有多个cpu,这样多个cpu能够并行的进行计算。

好处是:

1,吞吐量变大(即能够同时接收多个请求)

2,提高响应性(一个线程比较慢时,其他线程可以继续工作)

3,充分利用cpu资源。可以简单的理解,就是以前一个人做的事情,可以多个人独立分担去做了。

由于是多个线程独立的去做,那么肯定也会产生一些问题。

1,线程安全的问题:多个线程共享数据时,如果没有做相应的措施,那么就会产生数据一致性的问题,如读取脏数据(过期数据),丢失更新(某些线程做的更新被其他线程做的更新覆盖)

2,线程生命特征问题:单线程时一个线程串行执行不会产生问题,但是多个线程就会产生调度的问题,包括死锁,活锁(由于资源有限,调度问题,某个线程一直得不到资源)

3,上下文切换开销:一个线程的状态变更,调度停止线程的执行时,会保存该线程的上下文,即当时的环境状态,当重新执行时,需要恢复当时的环境状态,这个过程会产生开销。

4,可靠性 :线程之间是独立的,一方面一个线程意外终止了不会影响其他线程。另外一方面由于线程共享同一个进程中的资源,如果一个线程内存泄漏导致jvm崩溃停止,那么其他的线程也会停止。

通俗的来说:

有一个土堆要挖土,单线程的情况就是1个挖土机自己慢慢的挖,多线程就是10个挖土机同时来挖,好处就是快,坏处就是10个机器就会有调度的问题,保证不会抢夺资源、摩擦等问题,需要合理的处理调度。

二,线程的状态:

NEW:一个线程刚被创建,还未start(),一个线程只能一次处于此状态。

RUNNABLE:包括READY和RUNNING,线程执行start()之后就是READY状态,此时等待调度系统,被调用中就是RUNNING状态。如果执行yield()方法或者调度系统的原因,RUNNING状态也会变成READY状态,两者是能相互转化的。

BLOCKED:阻塞状态,即线程请求资源被其他线程调用,当其他资源使用完成之后,线程可以变为RUNNABLE状态。

WAITTING:无限制的等待其他线程先执行,才能执行。和BLOCKED的区别在于BLOCKED是线程获得不了资源被动的等待,WAITTING是主动的被调用者等待,相同点是需要等待别人执行完成才能执行。Object.wait() Thread.join() LockSupport.park()执行时会编程WAITTING状态,调用Object.notify() Object.notifyAll() LockSupport.unpark()能够编程RUNNABLE状态。

TIME_WAITTING:有闲时间的等待,比如等待1秒。

TERMINATED:终止状态,正常执行结束,或者跑出异常之后,都会编程这个状态。

总而言之:一个线程一定有一个NEW TERMINATED状态,其他状态可能都会有相互转化。(状态图见附件)

三,线程的实现

我们对线程的操作,基本基于对java.lang.Thread类来操作,Thread也是实现了Runnable接口。

线程实现 ① 实现Runnable接口,实现run方法,Thread类有一个传入Runnable实现的构造器,获得Thread ② 集成Thread类,重写run方法,获得Thread。

public class Instance {
    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnables());
        t1.start();
        Thread t2 = new MyThreads();
        t2.start();
    }
}
 
class MyRunnables implements Runnable{
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}
class MyThreads extends Thread{
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

四,线程常用方法

1,t.start()启动

2,t.isAlive()启动前是false,启动后是true

3,Thread.currentThread()获得当前线程

4,Thread.sleep(1000)睡眠

5,t.join()强行执行

6,t.yield()礼让

五,线程同步

多个线程占用相同的资源,为了避免脏数据的问题。

public class Synchronization {
 
    public static void main(String[] args) {
        MyRunable r = new MyRunable();
        Thread t1 = new Thread(r,"窗口1");
        Thread t2 = new Thread(r,"窗口2");
        Thread t3 = new Thread(r,"窗口3");
 
        t1.start();
        t2.start();
        t3.start();
    }
 
}
 
 
class MyRunable implements Runnable{
 
    private Integer ticket = 5;
 
    public void run() {
        synchronized (this){
            while (ticket > 0){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "卖出一张,剩余车票:" + (--ticket));
            }
        }
 
    }
}

打印结果:

窗口1卖出一张,剩余车票:4
窗口3卖出一张,剩余车票:3
窗口2卖出一张,剩余车票:2
窗口3卖出一张,剩余车票:1
窗口1卖出一张,剩余车票:0

对比没有家synchronized关键字结果:

窗口2卖出一张,剩余车票:4
窗口3卖出一张,剩余车票:3
窗口1卖出一张,剩余车票:2
窗口2卖出一张,剩余车票:1
窗口3卖出一张,剩余车票:0
窗口1卖出一张,剩余车票:-1
窗口2卖出一张,剩余车票:-2

对共享的变量或者方法上加上synchronized,也可以在代码块上加上这个关键字。

六,线程优先级

t1.setPriority(Thread.MAX_PRIORITY);
t1.setPriority(Thread.NORM_PRIORITY);
t1.setPriority(Thread.MIN_PRIORITY);

目前理解不深,之后补充。

时间: 2024-10-20 17:07:03

初识多线程的相关文章

java学习笔记之初识多线程

初识多线程 一.进程的认识: 1.进程的理解: 进程可以理解成正在执行的任务,就是正在运行的程序,进程又分为两种,一种是前台进程,就是我们很直观看见的,另一种是后台进程,就是操作系统启动就有的(系统级的进程),每个进程运行之后都会占用一定的cpu和内存资源: 比如说:我们打开window任务管理器就可以看到有很多的进程,里面有用户开启的,也有操作系统启动的进程 2.进程的调度: 也就是那么多的进程,cpu是怎样运行的呢? 采用时间片轮转法 二.线程认识 1.线程的理解 线程是在进程的内部运行的执

从头认识java-17.2 基本的线程机制(1)-初识多线程-2

接着上一个章节,我们这一章节介绍一下多线程的注意点. 线程间执行的顺序和时间是不同的 我们修改一下上一章节的代码: package com.ray.ch17; public class Test { public static void main(String[] args) { for (int i = 5; i < 8; i++) { DoneMission doneMission = new DoneMission(i); Thread thread = new Thread(doneMi

初识多线程之基础知识与常用方法

1.线程与进程的描述: 1.1进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1~n个线程.(进程是资源分配的最小单位) 1.2线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小.(线程是cpu调度的最小单位) 2.实现多线程的常用方式: 继承Thread类    extends Thread 实现Runnable接口  implements Runnable 内部匿名类 Thread t = new Th

多线程(一)初识多线程

一.环境 idea 二.为什么使用多线程 俗话说:众人拾柴火焰高.为什么不让一个人去拾柴呢!!!当然是团结啦!!但是最总要的是提高效率 所以在程序中也是一样,你可以讲一个线程看做一个人,为了加快程序效率就出现了多线程. 三.什么是线程 面试题:线程和进程的区别是什么 答:线程是程序的一条运行途径,进程是一个线程集合 四.创建线程的方式 多线程执行我们默认忽略极小误差默认是同时执行的,关于谁先执行就看谁能先强到CPU的执行权 4.1实现Thread类 public class ThreadTest

5天玩转C#并行和多线程编程 —— 第五天 多线程编程大总结

5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task 5天玩转C#并行和多线程编程 —— 第四天 Task进阶  一.多线程带来的问题 1.死锁问题  前面我们学习了Task的使用方法,其中Task的等待机制让我们瞬间爱上了它,但是如果我们在调用Task.WaitAll方法等待所有线程时,如果有一个Task一直不返

Java多线程编程总结一:多线程基本概念

Java多线程编程总结一 – 初识多线程 进程.多进程.线程.多线程的概念 进程(process):CPU的执行路径.通俗的说就是系统中正在运行的程序.比如我们打开了浏览器.QQ等等,这些程序一旦被打开运行了,就是所谓的进程. 多进程:系统中同时运行的多个程序.这个我们应该不难理解了,在打开浏览器的同时我们也可以QQ聊天.CS单机游戏等. 线程(thread):运行在进程中的运行单元.比如迅雷下载中我们的某一个下载任务就是一个线程. 多线程:同理可知,每个进程里面有多个独立的或者相互有协作关系的

老男孩Python高级全栈开发工程师【真正的全套完整无加密】

课程大纲 老男孩python全栈,Python 全栈,Python教程,Django教程,Python爬虫, scrapy教程,python高级全栈开发工程师,本套教程,4部分完整无缺,课程完结,官方售价6800元. 课程全部都是不加密,全部都有声音-不是网上那种几块钱十几块钱那种加密没有声音或者课程不全,贪便宜花冤枉钱不说都会严重影响学习,耽误大量时间! 本套全栈课程,不说完全媲美线下教学,只要你肯坚持,不会比面授差太多-坚持学完找一份python开发类的工作完全没问题,另外对于学习方面的投资

8天玩转并行开发——第四天 同步机制(上)

在并行计算中,不可避免的会碰到多个任务共享变量,实例,集合.虽然task自带了两个方法:task.ContinueWith()和Task.Factory .ContinueWhenAll()来实现任务串行化,但是这些简单的方法远远不能满足我们实际的开发需要,从.net 4.0开始,类库给我们提供了很多 的类来帮助我们简化并行计算中复杂的数据同步问题. 大体上分为二种: ①   并发集合类:           这个在先前的文章中也用到了,他们的出现不再让我们过多的关注同步细节. ②  轻量级同步

python-46-多线程

前言 线程:单个进程中执行中每个任务就是一个线程.线程是进程中执行运算的最小单位,代码/数据/文件是共享的. 就好像看作一个进程中还有多个线程执行任务,简单点来说就是一个程序运行中有多个线程在执行. 一.初识多线程 1.函数中多线程: # 初识多线程:threading from threading import Thread import time def func(i): time.sleep(2) print(i) if __name__ == '__main__': for i in r