基本概念

1、进程:程序的执行过程

2、线程:一个进程可以有单个线程也就是我们说的单线程,还可以有多个线程也就是我们说的多线程,

线程

1、当一个类继承了Thread类就可以当成一个线程用

2、我们会重写run方法写上我们自己的业务逻辑

3、run Thread类实现了RUnnable接口,静态代理模式

创建一个线程为什么是start不是直接调用run方法,如果直接调用run方法并没有创建一个线程,而是串行执行,start方法中的start0方法创建一个线程是由本地方法,是由JVM调用的

当一个类他已经继承了其他类,但是我们还想让其作为线程使用的话就可以让其实现Runable接口

package threaduse;

public class Thread01 {
public static void main(String[] args) {
Cat cat = new Cat();
//没有start方法
//cat.start();
Thread thread = new Thread(cat);
thread.start();
}
}
class Cat implements Runnable
{
int cnt = 0;
@Override
public void run() {
while(true)
{
System.out.println("小狗汪汪叫hi " + (++ cnt) + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if(cnt == 10) break;
}
}
}

多个子线程案例

package threaduse;

public class Thread03 {
public static void main(String[] args) {
T1 t1 = new T1();
T2 t2 = new T2();
Thread thread = new Thread(t1);
Thread thread1 = new Thread(t2);
thread1.start();
thread.start();
} } class T1 implements Runnable
{
int cnt = 0;
@Override
public void run() {
while(true)
{
System.out.println("hello world " + (++cnt));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if(cnt == 10) break;
}
}
}
class T2 implements Runnable
{
int cnt = 0;
@Override
public void run() {
while(true)
{
System.out.println("hi " + (++cnt));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if(cnt == 10) break;
}
}
}

模拟售票

package ticket;

//使用多线程模拟三个窗口同时售票
public class SellTicket {
public static void main(String[] args) {
SellTicket01 sellTicket01 = new SellTicket01();
SellTicket01 sellTicket011 = new SellTicket01();
SellTicket01 sellTicket012 = new SellTicket01();
sellTicket012.start();
sellTicket011.start();
sellTicket01.start();
}
} //使用继承Thread
class SellTicket01 extends Thread
{
private static int num = 100;
@Override
public void run() {
while(true)
{
if(num <= 0)
{
System.out.println("售票结束...");
break;
}
//休眠50ms
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
System.out.println("窗口 " + Thread.currentThread().getName() +
"售出一张票" + "剩余票数 = " + (-- num));
}
}
}

出现问题



票重复卖

这里先提出问题后续会解决啦

通知线程退出

package exit_;

public class Thread_Exit {
public static void main(String[] args) throws InterruptedException {
T t = new T();
t.start();
//如果我们希望main线程去控制t线程的终止,必须可以修改loop->通知方式
//休眠10s
Thread.sleep(10 * 1000);
t.setLoop(false);
}
} class T extends Thread
{
int cnt = 0; //设置一个变量
private boolean loop = true;
@Override
public void run() {
while(loop)
{
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("T还在运行" + (++ cnt));
}
} public void setLoop(boolean loop) {
this.loop = loop;
}
}

线程中断

线程的常用方法

1、start会调用run方法并且会创建一个新线程而单独调用run方法并不会创建新线程

2、interrupt,中断线程一般用于结束正在休眠的线程

3、sleep线程的休眠

3、现成的优先级

MAX、MIN、NORM

package Method;

import sun.awt.windows.ThemeReader;

public class ThreadMethod01 {
public static void main(String[] args) throws InterruptedException {
T t = new T();
t.setName("阿杜");
t.setPriority(Thread.MIN_PRIORITY);
t.start();
System.out.println(t.getName());
//主线程打印5个hi,然后就中断子线程的休眠
for(int i = 1; i <= 5; ++ i)
{
Thread.sleep(1000);
System.out.println("hi" + i);
}
t.interrupt();
}
} //自定义的线程类
class T extends Thread
{
@Override
public void run() {
while(true)
{
for(int i = 0; i < 100; ++ i)
{
//Thread.currentThread().getName()获取当前线程的名称
System.out.println(Thread.currentThread().getName() + "吃包子~~~~~" + i);
}
try {
System.out.println(Thread.currentThread().getName() + "休眠中~~~~~");
Thread.sleep(5000);
} catch (InterruptedException e) {
//InterruptedException捕获到一个中断异常
System.out.println(Thread.currentThread().getName() + "被 interrupt了");
}
} }
}

线程插队

yield:线程的礼让,让出cpu让其他线程先执行,让出的时间不确定,所以也不一定能成功让出

join:线程的插队,插队一旦成功,就一定会先执行完插队的进程

join方法调用的是对方的,也就是你想让插队的那个线程的

例题

package Method;

public class ThreadMethodExercise {
public static void main(String[] args) throws InterruptedException {
T3 t3 = new T3();
Thread thread = new Thread(t3);
for(int i = 1; i <= 10; ++ i)
{
System.out.println("hi " + i);
if(i == 5)
{
thread.start();
thread.join();
}
}
}
} class T3 implements Runnable
{
@Override
public void run() {
for(int i = 1; i <= 10; ++ i)
{
System.out.println("hello " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}

用户线程和守护线程

用户线程:也叫工作线程,当线程的任务执行完或以通知的形式结束

守护线程:一般是为用户线程工作的,当所有用户线程结束守护线程自动结束

常见的守护线程:垃圾回收机制

package Method;

public class ThreadMethod03 {
public static void main(String[] args) throws InterruptedException {
MyDaemonThread myDaemonThread = new MyDaemonThread();
//我们希望当主线程结束后子线程能自动结束,我们需要将子线程设置为守护线程
myDaemonThread.setDaemon(true);
myDaemonThread.start();
for (int i = 1; i <= 10; ++i)
{
System.out.println("阿杜在辛苦的工作");
Thread.sleep(1000);
}
}
} class MyDaemonThread extends Thread
{
@Override
public void run() {
for(;;)
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("阿杜和阿范一直在聊天~~~~~");
}
}
}

线程的七大状态



线程同步

在多线程中,对一些敏感数据可能同一时刻只允许一个线程访问,为了保证数据的完整性,任何同一时刻我们都只让一个线程访问

synchronized

package syn;

class SellTicket03 implements Runnable
{
private static int num = 100;
private boolean loop = true;
public synchronized void sell(){
if(num <= 0)
{
System.out.println("售票结束。。。。");
loop = false;
return;
}
while(loop)
{
if(num <= 0)
{
System.out.println("售票结束...");
break;
}
//休眠50ms
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
System.out.println("窗口 " + Thread.currentThread().getName() +
"售出一张票" + "剩余票数 = " + (-- num));
}
} @Override
public void run() {
sell();
}
}
//使用多线程模拟三个窗口同时售票
public class SellTicket {
public static void main(String[] args) {
SellTicket03 sellTicket03 = new SellTicket03();
SellTicket03 sellTicket031 = new SellTicket03();
Thread thread = new Thread(sellTicket03);
Thread thread1 = new Thread(sellTicket031);
thread.start();
thread1.start();
}
}

互斥锁

上面的同步机制就是利用了锁,当多个线程运行时,他们先争夺锁,只有获得锁的线程才能执行方法,上面的售卖票利用的就是互斥锁

1、java引入互斥锁的概念是为了保证共享数据的完整性

2、互斥锁,用关键字synchronized修饰时表明该对象在任何同一时刻只能有一个线程访问

3、同步之后因为同一时刻只有一个线程在执行,所以效率自然会降低

4、如果锁加在方法上,如果方法是静态的,锁加在类上,如果方法是非静态的,锁加在当前对象(this)上或则其他对象上(并不是很理解呜呜呜~~~~~)

互斥锁想要起作用,多个线程锁的对象必须是同一个

死锁

双方都需要当前对方所拥有的锁资源

package syn;

public class DeadLock_ {
public static void main(String[] args) {
DeadLockDemo deadLockDemo = new DeadLockDemo(false);
DeadLockDemo deadLockDemo1 = new DeadLockDemo(true);
deadLockDemo1.start();
deadLockDemo.start();
}
} class DeadLockDemo extends Thread
{
static Object o1 = new Object();
static Object o2 = new Object();
boolean flag; public DeadLockDemo(boolean flag) {
this.flag = flag;
} @Override
public void run() {
if(flag)
{
synchronized (o1)
{
System.out.println(Thread.currentThread().getName() + "进入了o1");
synchronized (o2)
{
System.out.println(Thread.currentThread().getName() + "进入了o2");
}
}
}else{
synchronized (o2)
{
System.out.println(Thread.currentThread().getName() + "进入了o2");
synchronized (o1)
{
System.out.println(Thread.currentThread().getName() + "进入了o1");
}
}
}
}
}

释放锁

释放锁



不会释放锁

Java进程(基础)的更多相关文章

  1. Java多线程基础:进程和线程之由来

    转载: Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够 ...

  2. Java并发基础:进程和线程之由来

    转载自:http://www.cnblogs.com/dolphin0520/p/3910667.html 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程. ...

  3. 1、Java多线程基础:进程和线程之由来

    Java多线程基础:进程和线程之由来 在前面,已经介绍了Java的基础知识,现在我们来讨论一点稍微难一点的问题:Java并发编程.当然,Java并发编程涉及到很多方面的内容,不是一朝一夕就能够融会贯通 ...

  4. [转]Java多线程干货系列—(一)Java多线程基础

    Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...

  5. Java 多线程——基础知识

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  6. JAVA面试基础

    JAVA相关基础知识1.面向对象的特征有哪些方面 ?1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂 ...

  7. 【重走Android之路】【Java面向对象基础(三)】面向对象思想

    [重走Android之路][基础篇(三)][Java面向对象基础]面向对象思想   1 面向对象的WWH   1.1 What--什么是面向对象         首先,要理解“对象”.在Thinkin ...

  8. Java 并发基础

    Java 并发基础 标签 : Java基础 线程简述 线程是进程的执行部分,用来完成一定的任务; 线程拥有自己的堆栈,程序计数器和自己的局部变量,但不拥有系统资源, 他与其他线程共享父进程的共享资源及 ...

  9. 我的学习目标(目前已初步学习完Java语言基础)

    操作系统.尤其是内存/线程/进程方面 计算机网络协议,重点关注 TCP/UDP/HTTP. 数据结构与算法. 数据库 设计模式,熟练掌握常用的几种设计模式. Java语言基础.熟悉java语言基础,了 ...

  10. Java并发基础概念

    Java并发基础概念 线程和进程 线程和进程都能实现并发,在java编程领域,线程是实现并发的主要方式 每个进程都有独立的运行环境,内存空间.进程的通信需要通过,pipline或者socket 线程共 ...

随机推荐

  1. Vue学习之认识ref

    ref相当于一个dom节点,值为string 通俗将类似于原生js的document.querySelector('xxx'):但是不同的是vue是操纵虚拟dom,在渲染初期并没有这个属性,而是在创建 ...

  2. 掌握把“烂”SQL牢牢关进笼子里的密钥

    摘要:本文通过5个部分内容帮助开发者快速了解GaussDB(DWS) 资源管理机制,让数仓过载烦恼不再,把"烂"SQL牢牢关进笼子里. 本文分享自华为云社区<直播回顾 | 掌 ...

  3. ASP.NET MVC4 学习笔记-3

    创建一个简单的数据录入程序--Create a Simple Data-Entry Application 在这篇博客中,我们将通过创建一个简单的数据录入程序来探索MVC的其他特点.在这一节中我们要跟 ...

  4. PNG结构

    参考此博客 PNG的文件头总是固定的八个字节 89 50 4E 47 0D 0A 1A 0A 数据块长度13 00 00 00 0D 文件头数据块标识IDCH 49 48 44 52 13位数据块(I ...

  5. 帮老娘导入SF信息

    转自自己的QQ空间 2023/1/3 老娘公司要统计Excel 简单说就是把顺丰上面寄的85个快递填到表里去 再把没有寄的从那两张表加起来130多个人里面揪出来单独填表 有些企业的Excel就是个灾难 ...

  6. Hugging Face 的文本生成和大语言模型的开源生态

    [更新于 2023 年 7 月 23 日: 添加 Llama 2.] 文本生成和对话技术已经出现多年了.早期的挑战在于通过设置参数和分辨偏差,同时控制好文本忠实性和多样性.更忠实的输出一般更缺少创造性 ...

  7. 开机自动打开termux以及启动termux的服务

    ps:因为我们的服务是安装在平板上面的termux,客户不想维护麻烦,如果平板重启之后还需要手动启动ternux,还要开启命令启动服务,这样比较麻烦,所以研究如下操作 1.安装macroDroid 直 ...

  8. Java内存溢出时,还能正常处理请求吗?

    当你被问到"当Java程序发生内存溢出时,进程还能正常处理请求吗?"这样的面试题,会不会很懵?这里分享一次网友车辙在当初刚毕业那几年,意义风发,总觉得天下没有自己不会的面试题.然后 ...

  9. docker-compose快速部署elasticsearch-8.x集群+kibana

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 前文<Docker下elasticse ...

  10. uni-app+h5puls 编写相机拍照

    <template> <view class="camera-page"> <image :src="imgSrc" v-if=& ...