线程

概念

1.程序:为解决某种问题,使用计算机语言编写的一系列指令(代码)的集合

2.进程:正在运行的程序(被加载到内存中),是操作系统进行资源分配的最小单位

3.线程:进程可以进一步细化为线程(比进程更小)且线程是隶属于进程的,是操作系统执行的最小的执行单元 也是cpu进行任务调度的最小单位

  • 如 :运行的QQ也是一个进程,操作系统就会为这个进程分配资源 一个聊天窗口就是一个线程,线程隶属于进程

tips:早期是没有线程的,是以进程为单位执行的,进程的单位比较大,当一个进程运行时,其他进程就不能执行了,所以后来,将进程中的多个任务细化为线程,cpu的执行单位,也是从进程进化为更小的线程

总结

  1. 一个进程可以包含多个线程
  2. 一个线程只能隶属于一个进程,线程不能脱离进程单独独立运行
  3. 一个进程中至少有一个线程,即主线程,javamian方法就是用来启动主线程
  4. 在主线程中可以创建并启动其他线程,所有线程都共享进程的内存资源
  5. 所有线程都共享进程资源

Thread类

JavaThread表示线程,提供了许多的方法,来对线程的控制,可以通过继承Thread 类来实现线程

Thread常用方法

  • Thread.currentThread();

    • 获取当前运行的线程
  • run();
    • 线程要执行的任务
  • start();
    • 启动Java线程
  • setName(String name);
    • 设置线程名字
  • (String)getName();
    • 获取线程名字
  • getPriority();
    • 获取线程优先级
  • setPriority();
    • 设置线程优先级 1~10一般线程默认优先 5
  • sleep(long ms);
    • 设置线程休眠
  • join();
    • 让其他线程等待这个线程结束后,其他线程再执行

Thread构造方法

  • new Thread(Runnable runnable);

    • 接受一个任务对象
  • new Thread(Runnable runnable,String name);
    • 接受一个对象 并为对象设置名字

使用上面方法进行实例

线程1
public class MyThread extends Thread{ //重写run方法,在run中执行我们要执行的方法
@Override
public void run() {
for(int i=0;i<10000;i++){
System.out.println("循环main"+i);
}
} }
线程2
public class MyThread2 extends Thread {
@Override
public void run() {
for(int i=0;i<10000;i++){
System.out.println("循环main2"+i);
}
}
}
public class 线程 {
public static void main(String[] args) {
for(int i=0;i<10000;i++){
System.out.println("循环1 "+i);
}
for(int i=0;i<10000;i++){
System.out.println("循环2 "+i);
}
for(int i=0;i<10000;i++){
System.out.println("循环3 "+i);
}
for(int i=0;i<10000;i++){
System.out.println("循环4 "+i);
}
/*
这样不管怎么执行都是单线程,从上到下依次执行, 所以如果想在java程序中有几件不想管的事件同时执行
可以在java中创建线程,把一些需要执行的任务放在线程中执行,
这样就拥有让cup执行的权利
*/
MyThread myThread = new MyThread();
//调用start方法让程序多线程进行,重写run方法但不能调用run,不然只是普通方法的调用,依然是单线程
myThread.start();
MyThread2 myThread2 = new MyThread2();
myThread2.start(); } }

观察结果 可知 MyThreadMyThread2是同时进行的

Runnable接口

Java中我们也可以实现Runnable接口来进行对线程的实现

思路.

  • 创建一个类 实现Runnable接口 重写run方法

  • 在main函数使用Thread构造方法传入Runnable对象

  • public class MyTask implements Runnable{
    @Override
    public void run() {
    for(int i=0;i<10;i++){
    System.out.println("啊");
    }
    }
    }
  • MyTask myTask = new MyTask();
    //创建一个线程
    Thread thread = new Thread(myTask);

Callable接口

Java中也可以实现Callable接口 重写 call()方法 来对线程的实现

思路.

  • 重写call()方法 call()方法有返回值 可以抛出异常,还可以处理不同类型
  • 依然使用Thread构造方法来创建一个线程

关于线程的其他概念

线程生命周期

从线程到销毁期间经历五个状态

守护线程(也是线程的一种)

  • setDaemon();如果一个线程守护线程,那么它会等待java中其他线程任务结束后,自动终止
  • 守护线程是为其他线程提供服务的,eg:jvm中的垃圾回收机制,就是一个守护线程

多线程

在一个应用程序中,存在多个线程,不同线程可以并行的执行任务

操作系统线程任务调度算法

  1. 先来先服务调度算法
  2. 短作业优先调度算法
  3. 优先级调度算法
  4. 高响应比优先调度算法
  5. 时间片轮转调度算法
  6. 多级反馈队列调度算法(集合前几种算法的优点)

对线程进行加锁

分析

  • 多线程的优点

    • 提高程序的处理能力
    • 提高CPU的 利用率
  • 缺点
    • 线程也是需要占用内存资源和CPU资源
    • 多个线程对同一个共享资源进行访问,会出现线程安全问题

对于内存资源与CPU资源我们可以通过不断增加内存来解决

对于线程安全问题 我们则需要对 线程进行加锁

synchronized

synchronized 修饰代码块需要加一个同步对象 synchronized(同步对象)

同步对象要求

  • 多线程用到的对象必须是同一个对象
  • 可以是java类中任何类对象.
  • 作用:用来记录有没有线程进入到同步代码块中

修饰方法

  • 锁不需要我们提供,会默认提供锁对象
  • synchronized如果修饰的是非静态方法,锁的对象是this
  • 如果是静态方法,锁的对象是Class的对象 (一个类只能有一个对象)

修饰代码块例子

package day17;

public class PrintNums implements Runnable{
//实现线程的交替打印
int num=100;
Object object = new Object();
@Override
public void run() {
while(true){
synchronized (object){
object.notify();//唤醒线程
if(num==0){
break;
}
System.out.println(Thread.currentThread().getName()+"."+num+".");
num--;
try {
object.wait();//线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
package day17; public class TestPrintNums {
public static void main(String[] args) {
PrintNums printNums = new PrintNums();
Thread t1 = new Thread(printNums,"1");
Thread t2 = new Thread(printNums,"2");
Thread t3 = new Thread(printNums,"3");
t1.start();
t2.start();
t3.start();
}
}

于是我们实现了交替打印 每次只能进入一个线程

修饰方法(同步对象会有默认的)

  1. 锁不需要我们提供,会默认提供对象锁
  2. synchronized如果修饰的是非静态方法,锁的对象是this

synchronized如果修饰的是静态方法,锁的对象是类的Class对象,一个类只有 一个对象

  • 如果是非静态方法,那么同步对象是this(如果是非静态对象,我们可以使用Runnable创建线程方法)

  • 如果是静态方法,所得对象是当前类的Class对象

  • 当前类的Class对象:一个类加载到内存后会为这个类创建唯一的Class类的对象

  • Class类实例表示正在运行的Java应用程序中的类和接口

  • 修饰静态方法
    public class SellTicket extends Thread {
    static int counts = 10;//10张票
    static Object object = new Object(); @Override
    public void run() { while (counts > 0) {
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    sellTicket();
    }
    } public static synchronized void sellTicket() {
    if(counts>0){
    System.out.println(Thread.currentThread().getName()+"买了"+counts+"张票");
    --counts;
    }
    }
    }
    public class Test {
    public static void main(String[] args) {
    SellTicket t1 = new SellTicket();
    t1.setName("窗口1");
    SellTicket t2 = new SellTicket();
    t2.setName("窗口2"); t1.start();
    t2.start();
    }
    }

  • 修饰非静态方法
    public class SellTickets2 implements Runnable{ int t=20;//票数 @Override
    public void run() {
    while(t>0){
    try {
    Thread.sleep(100);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    sell2();
    }
    }
    public synchronized void sell2(){
    if(t>0){
    System.out.println(Thread.currentThread().getName()+"买了"+t+"张票");
    --t;
    }
    }
    } public class Test2 {
    public static void main(String[] args) {
    SellTickets2 sellTickets2 = new SellTickets2();
    Thread t1 = new Thread(sellTickets2,"窗口1");
    Thread t2 = new Thread(sellTickets2,"窗口2"); t1.start();
    t2.start();
    }
    }

ReentrantLock类加锁

  • 只能对某一代码块进行加锁,不能对整个方法加锁
  • 加锁方法如下
ReentrantLock r = new ReentrantLock();//创建 ReentrantLock对象
r.lock();<---------|//加锁
|
............. |------被锁部分(一次只进去一个线程)
|
r.unlock();<-------|//解锁

tips:r.unlock();最好写在finally{};代码块中,保证发生异常时,也能够解锁;

synchronized与ReentrantLock的区别

  1. synchronized是一个关键字,ReentrantLock是一个类

  2. synchronized修饰代码块和方法,ReentrantLock只能修饰代码块

  3. synchronized可以隐式的加锁和释放锁,运行出现异常可以自动释放锁

    ReentrantLock需要手动加锁和释放锁,建议在finally代码中释放锁

常用的三个方法 wait notify notifyAll

  • wait();方法使当前线程进入等待状态,直到另一个线程调用该对象的notify()notifyAll()方法来唤醒它

  • notify();方法唤醒在该对象上调用wait()方法进入等待状态的一个线程,如果有多个线程在等待,则只会唤醒其中一个线程。

  • notifyAll();方法唤醒在该对象上调用wait()方法进入等待状态的所有线程。

    tips:1.都是Object类中定义的方法

    ​ 2.三个方法必须在同步代码块中使用

    ​ 3.这三个方法必须通过为锁的对象调用

Java线程概念集合的更多相关文章

  1. JAVA线程概念

    一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在 ...

  2. java 线程安全集合

    ConcurrentMap 线程安全的HashMap CopyOnWriteArrayList 读多写少的线程安全的ArrayList,性能比vector好. ConcurrentLinkedQueu ...

  3. Java线程:概念与原理

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  4. java 线程​基本概念 可见性 同步

    开发高性能并发应用不是一件容易的事情.这类应用的例子包括高性能Web服务器.游戏服务器和搜索引擎爬虫等.这样的应用可能需要同时处理成千上万个请求.对于这样的应用,一般采用多线程或事件驱动的架构.对于J ...

  5. Java中各种集合(字符串类)的线程安全性!!!

    Java中各种集合(字符串类)的线程安全性!!! 一.概念: 线程安全:就是当多线程访问时,采用了加锁的机制:即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到该线程读 ...

  6. Netty核心概念(7)之Java线程池

    1.前言 本章本来要讲解Netty的线程模型的,但是由于其是基于Java线程池设计而封装的,所以我们先详细学习一下Java中的线程池的设计.之前也说过Netty5被放弃的原因之一就是forkjoin结 ...

  7. Java线程:概念与使用

    Java线程大总结 原文章地址:一篇很老的专栏,但是现在看起来也感觉深受启发,知识点很多,很多线程特点我没有看,尴尬.但是还是整理了一下排版,转载一下. 操作系统中线程和进程的概念 在现代操作系统中, ...

  8. Java线程:概念与原理(转)

    一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程.比如在 ...

  9. 《Java基础知识》Java线程的概念

    按照规划,从本篇开始我们开启『并发』系列内容的总结,从本篇的线程开始,到线程池,到几种并发集合源码的分析,我们一点点来,希望你也有耐心,因为并发这块知识是你职业生涯始终绕不过的坎,任何一个项目都或多或 ...

  10. -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中

     本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法的区别 为什么wait( ...

随机推荐

  1. huggingface vit训练CIFAR10数据集代码 ,可以改dataset训练自己的数据

    上代码,使用hugging face fineturn vit模型 自己写的代码 from transformers import ViTImageProcessor, ViTForImageClas ...

  2. 关于console.log中this指向的问题

  3. 【pytorch学习】之数据预处理

    2 数据预处理 为了能用深度学习来解决现实世界的问题,我们经常从预处理原始数据开始,而不是从那些准备好的张量格式数据开始.在Python中常用的数据分析工具中,我们通常使用pandas软件包.像庞大的 ...

  4. git fatal detected dubious ownership in repository 的解决方法

    我换了一台电脑,将旧电脑的硬盘换到新电脑上:我装了双系统,切换到另一个系统时:我发现了 git 代码仓库无法执行 git 命令,不断报错 fatal: detected dubious ownersh ...

  5. Win32 使用 CreateProcess 方法让任务管理器里的命令行不显示应用文件路径

    本文记录一个 Win32 的有趣行为,调用 CreateProcess 方法传入特别的参数,可以让任务管理器里的命令行不显示应用文件路径 开始之前,先看看下面这张有趣的图片 可以看到我编写的 Svca ...

  6. dotnet 在 UOS 国产系统上使用 MonoDevelop 进行拖控件开发 GTK 应用

    先从一个 Hello World 应用开始,试试和古老的 WinForms 一样的拖控件式开发 在创建完成一个 GTK# 2.0 应用之后,咱可以试试开始拖控件的开发,当然这个开发方式开发出来的应用界 ...

  7. 2019-8-31-dotnet-线程静态字段

    title author date CreateTime categories dotnet 线程静态字段 lindexi 2019-08-31 16:55:58 +0800 2019-06-13 0 ...

  8. 9.prometheus监控--监控springboot2.x(Java)

    一.环境部署 yum search java | grep jdk yum install -y java-11-openjdk-devel 二.监控java应用(tomcat/jar) JMX ex ...

  9. 6.prometheus监控--监控redis/rabbitmq/mongodb

    1.监控redis 1.1 redis_exporter安装方式 1.1.1 二进制源码安装方式 参考nginx二进制安装方法 redis_exporter下载地址:https://github.co ...

  10. 【转载】只有.dbf数据文件进行数据库恢复

    此篇文章为转载,来自 " ITPUB博客 " ,链接:http://blog.itpub.net/26015009/viewspace-714742/ 个人mark下,在之后dbf ...