1、 线程概念

                  

a)     什么是主线程              

Java程序启动过程中自动创建的并执行main方法的线程称为主线程

  • 主线程的执行路径:

    从main方法开始到main方法结束

b)什么是子线程

除了主线程的其它所有线程都是子线程。

  • 子线程的执行路径:

    从run方法到run方法结束

            

          

C)线程的运行模式

  • 分时式模式:每个线程平均分配CPU使用权,每一个线程使用CPU的时间是相同的。
  • 抢占式模式:优先级高的线程抢到CPU的概率高,如果优先级都相同,就是随机抢占cpu的使用权
  • Java程序的线程运行模式属于抢占式模式

2、 多线程内存图解

    三句重要的小结:

    每一个线程都会有自己独立的栈空间

    进程的堆空间是被该进程的所有线程共享

    在同一个线程中,代码是按顺序从上向下执行的。

 

3、 创建线程的两种方式

3.1创建一个类继承Thread类

重写run方法:将线程任务写在run()方法体内

调用start()方法,开启线程干活

例子:

 package com.yangzhihui.level03.test02;

 import java.util.Random;

 public class ThreadDemo {
public static void main(String[] args) {
MyThread myThread01 = new MyThread("线程1:");
MyThread myThread02 = new MyThread("线程2:");
myThread01.start();
myThread02.start();
}
} class MyThread extends Thread {
public MyThread(String name) {
super(name);
} @Override
public void run() {
Random random = new Random(); int sum = 0;
for (int i = 0; i < 30; i++) {
int num;
num = random.nextInt(901) + 100;
sum += num;
System.out.println(Thread.currentThread().getName() + num);
} System.out.println("10个100~1000随机数的和是:" + Thread.currentThread().getName() + sum);
}
}

 

3.2 实现Runnable

  • 步骤:

    A)创建一个类实现Runnable接口,重写方法:将线程任务相关的代码写在run方法中

    B) 创建实现类对象,根据实现类对象创建Thread对象

    C) 调用线程对象的start方法开启线程:会在新的路径中执行run方法

  • 使用Runnable接口的好处:

    屏蔽了Java类单继承的局限性

    可以更好的在多线程之间共享数据

    将线程和任务进行分离,降低了程序的耦合性

    为线程池提供前提条件

  • 匿名内部类

    什么时候使用匿名内部类创建线程

    当任务只需要执行一次时,可以考虑使用匿名内部类

例子:

实现Runnable接口
1.定义一个子任务类,实现Runnable接口;
2.在子任务类中重写run方法,在run方法中打印子线程的名称;
3.定义一个测试类;
4.在main方法中打印主线程的名称;
5.在main方法中创建一个子任务对象;
6.在main方法中创建一个Thread类的对象,并把子任务对象传递给Thread类的构造方法;
7.调用Thread类对象的start方法开启子线程;

 package level01.test03;

 class MyRunnable03 implements Runnable {
@Override
public void run() {
System.out.println("实现接口方式:子线程的名称--" + Thread.currentThread().getName());
}
} package level01.test03; public class TestMain {
public static void main(String[] args) {
//打印主线程的名称
System.out.println(Thread.currentThread().getName()); //通过Runnable接口实现类对象,开启多线程
MyRunnable03 myRunnable03 = new MyRunnable03();
new Thread(myRunnable03, "线程2").start();
}
}

4、 线程安全

4.1 概念

指两个或两个以上的线程在同时操作一个共享资源时仍然得到正确的结果则就是线程安全。

  • 线程安全的案例

     火车站买票案例

            

4.2实现线程安全的方式

4.2.1:同步代码块

同步:每一个线程按顺序执行

异步:可以同时执行(多线程的代名词)

同步代码块格式:

Synchronized(锁对象){

//操作共享资源的代码

}

同步代码块的原理:

能够保证同一时间只有一个对象操作共享资源的代码

锁对象注意事项:

锁对象可以使任意类型的对象。

所有线程必须共用一把锁

例子:

1. 有100个限量版的水杯,但是只能通过实体店和官网才能进行购买,并且分别统计卖了多少。请用线程进行模
拟并设置线程名称用来代表售出途径,再将信息打印出来。
比如(实体店卖出第1个,总共剩余n个..)

 package level01.test06;

 public class Cup implements Runnable{
private int sellNum = 0;
private final int NUM = 100;
private String cupLock = "lock";
@Override
public void run() {
while(true){
synchronized (cupLock){
if(sellNum < NUM){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖出第" + (++sellNum) +
"个,总共剩余" + (NUM - sellNum));
}else {
System.out.println(Thread.currentThread().getName() + "买完了");
break;
}
}
}
}
} package level01.test06; public class TestMain {
public static void main(String[] args) {
Cup cup = new Cup(); new Thread(cup, "实体店").start();
new Thread(cup, "官网").start();
}
}

4.2.2 同步方法

同步方法格式:
       修饰符 synchronized
返回值类型 方法名(参数列表){…}

同步方法:

能够保证同一时间,只有一个线程执行方法体内的代码

同步方法的注意事项

  • 静态同步方法锁对象是:类名.class

    附录:每一个类都会有一个Class对象,而且是唯一的。

    Class c1 = TicketThread.class;

    Class c2 = TicketThread.class;

  • 非静态同步方法锁对象是:this
  • 静态方法和非静态方法的选择

    当方法体内部需要访问到任何非静态成员时,可以定义为静态方法。否则定义为非静态方法。

例子:

1. 有一辆班车除司机外只能承载80个人,假设前中后三个车门都能上车,如果坐满则不能再上车。请用线程模
拟上车过程并且在控制台打印出是从哪个车门上车以及剩下的座位数。
比如:(前门上车---还剩N个座...)

 package level01.test07;

 public class Bus implements Runnable {
private final int NUM = 80;
private int seatNum = 0; @Override
public void run() {
while(seatNum < NUM){
aboardBus();
}
System.out.println("车座已满");
} public synchronized void aboardBus(){
if(seatNum < NUM){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
seatNum++;
System.out.println("从" + Thread.currentThread().getName() +
"上车,剩下" + (NUM - seatNum) + "座位");
}
}
} package level01.test07; import java.io.BufferedWriter; public class TestMain {
public static void main(String[] args) {
Bus bus = new Bus(); new Thread(bus, "前门").start();
new Thread(bus, "中门").start();
new Thread(bus, "后门").start();
}
}

4.2.3

Lock接口:提供了比synchronized代码块和synchronized方法更广泛的锁操作,同步代码块/同步方法具有的功能Lock都有,除了之外更强大,更体现面向对象。

  • 常用方法:

lock():上锁

   unlock():释放锁

  • Lock使用注意事项

    lock()和unlock()必须成对出现。一定要 注意在线程执行完共享代码后,要释放锁。

例子:

写一个卖票的程序,
1. 写一个类,该类继承Thread,定义一个变量记录总票数。
2. 开启四个卖票窗口(开始四个线程),同时执行卖票的程序。
要求每卖一张票在控制台输出:当前窗口为:窗口a卖了一张票,剩余票数为19。其中窗口a为线程的名字。

 package level01.test08;

 import java.util.concurrent.locks.ReentrantLock;

 public class Ticket implements Runnable{
private final int NUM = 20;
private int seatNum = 0;
private ReentrantLock seatLock = new ReentrantLock(); @Override
public void run() {
while(seatNum < 20){
seatLock.lock(); try {
if(seatNum < NUM){
Thread.sleep(100);
seatNum++;
System.out.println("当前窗口:" + Thread.currentThread().getName() +
"卖了一张牌,剩余票数为" + (NUM - seatNum));
}else {
System.out.println(Thread.currentThread().getName() + "票卖完了");
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
seatLock.unlock();
}
}
}
} package level01.test08; public class TestMain {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(ticket,"线程1:").start();
new Thread(ticket,"线程2:").start();
new Thread(ticket,"线程3:").start();
new Thread(ticket,"线程4:").start();
}
}

5、 线程状态

NEW(新建):新建状态,刚刚创建出来,还没有调用start方法

Runnable(可运行):可运行状态,有资格运行,可能正在运行中,也可以不是正在运行

Blocked(锁阻塞):等待其他线程释放锁对象

Wating(无限等待):无限等待

TimedWating(计时等待):限时等待,调用了sleep方法或者wait(毫秒数),需要被其他线程调用notify方法唤醒

Teminated(被终止):死亡状态,任务执行完毕或调用了stop方法

                    

            

                     

day006-多线程的更多相关文章

  1. Python中的多进程与多线程(一)

    一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...

  2. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  3. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  4. Java多线程

    一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程.   进程:进程 ...

  5. .NET基础拾遗(5)多线程开发基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

  6. Java多线程基础——对象及变量并发访问

    在开发多线程程序时,如果每个多线程处理的事情都不一样,每个线程都互不相关,这样开发的过程就非常轻松.但是很多时候,多线程程序是需要同时访问同一个对象,或者变量的.这样,一个对象同时被多个线程访问,会出 ...

  7. C#多线程之线程池篇3

    在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...

  8. C#多线程之线程池篇2

    在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...

  9. C#多线程之线程池篇1

    在C#多线程之线程池篇中,我们将学习多线程访问共享资源的一些通用的技术,我们将学习到以下知识点: 在线程池中调用委托 在线程池中执行异步操作 线程池和并行度 实现取消选项 使用等待句柄和超时 使用计时 ...

  10. C#多线程之线程同步篇3

    在上一篇C#多线程之线程同步篇2中,我们主要学习了AutoResetEvent构造.ManualResetEventSlim构造和CountdownEvent构造,在这一篇中,我们将学习Barrier ...

随机推荐

  1. edX MITx: 6.00.1x Introduction to Computer Science and Programming Using Python 课程 Week 1: Python Basics Problem Set 1 Problem 3

    Assume s is a string of lower case characters. Write a program that prints the longest substring of  ...

  2. 最小生成树----prim算法的堆优化

    题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz 输入输出格式 输入格式: 第一行包含两个整数N.M,表示该图共有N个结点和M条无向边.(N<=5000,M<= ...

  3. 2017西安区域赛A / UVALive - 8512 线段树维护线性基合并

    题意:给定\(a[1...n]\),\(Q\)次询问求\(A[L...R]\)的异或组合再或上\(K\)的最大值 本题是2017的西安区域赛A题,了解线性基之后你会发现这根本就是套路题.. 只要用线段 ...

  4. es6 封装一个基础的表单验证

    1, 需求分析 设计一个通用的表单验证,如果后期表单中添加了更多的需求,不需要更改之前的代码逻辑,最好不要改之前的代码,需要加什么直接加就好了. 2,代码分析 此表单验证最好返回一个函数,在api设计 ...

  5. javascript 中typeOf

    JS中的变量是松散类型(即弱类型)的,可以用来保存任何类型的数据. typeof 可以用来检测给定变量的数据类型,可能的返回值: 1. 'undefined' --- 这个值未定义: 2. 'bool ...

  6. (转)求有向图的强连通分量个数(kosaraju算法)

    有向图的连通分量的求解思路 kosaraju算法 逛了很多博客,感觉都很难懂,终于找到一篇能看懂的,摘要记录一下 原博客https://www.cnblogs.com/nullzx/p/6437926 ...

  7. Java 继承初探

    Java继承的基础 Java中,被继承的类叫做超类,继承超类的类叫子类.(一个子类亦可以是另一个类的超类) 继承一个类,只需要用关键字 extends 把一个类的定义合并到另一个类中就可以了. 例子中 ...

  8. 使用jenkins自动化构建android和ios应用

    背景 随着业务需求的演进,工程的复杂度会逐渐增加,自动化的践行日益强烈.事实上,工程的自动化一直是我们努力的目标,能有效提高我们的生产效率,最大化减少人为出错的概率,实现一些复杂的业务需求应变.场景如 ...

  9. pytorch 安装

    安装pytorch时,官网不能选择版本.原以为是浏览器问题,换了几个浏览器都不行. 后来FQ之后,就能选择版本了. sudo pip install torch torchvision

  10. 迪米特法则(Law of Demeter)LoD

    using System; using System.Collections.Generic; using System.Text; namespace LawOfDemeter { //也叫Leas ...