什么是程序?一个程序可以有多个进程
程序是一段静态的代码,它是应用程序执行的蓝本。
什么是进程?一个进程可以有多线程
进程是指一种正在运行的程序,有自己的地址空间。
作为蓝本的程序可以被多次加载到系统的不同内存区域分别执行,形成不同的进程。
基于进程的特点是允许计算机同时运行两个或更多的程序。
什么是线程?
线程是进程内部单一的一个顺序控制流。 一个进程在执行过程中,可以产生多个线程。每个线程也有自己产生、存在和消亡的过程。
并发当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。
并行:当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
区别:并发和并行是即相似又有区别的两个概念,并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地交替执行。倘若在计算机系统中有多个处理机,则这些可以并发执行的程序便可被分配到多个处理机上,实现并行执行,即利用每个处理机来处理一个可并发执行的程序,这样,多个程序便可以同时执行。
/*
* Copyright 2006-2021 webrx Group.
*/
package cn.webrx;
/**
*
*
*
*
* @author webrx [webrx@126.com]
* @version 1.0
* @date 2021-01-28 14:24:09
*/
public class Thread2 implements Runnable{
public void run() {
System.out.println("Thread2....");
}
}
12.2.2 继承Thread类
/*
* Copyright 2006-2021 webrx Group.
*/
package cn.webrx;
/**
*
*
*
*
* @author webrx [webrx@126.com]
* @version 1.0
* @date 2021-01-28 14:27:03
*/
public class Thread3 extends Thread{
public void run() {
System.out.println("Thread3");
}
}
12.2.3 综合线程实现
/*
* Copyright 2006-2021 webrx Group.
*/
package cn.webrx;
/**
*
*
*
*
* @author webrx [webrx@126.com]
* @version 1.0
* @date 2021-01-28 14:19:03
*/
public class Thread1 {
public static void main(String[] args) {
System.out.println("hello world main thread");
//建立方法一 实现Runnable接口,并作为Thread类参数
new Thread(() -> {
System.out.println("Thread1");
}).start();
Thread t2 = new Thread(new Thread2());
t2.start();
//建立方法二 继承Thread 类,重写run方法
var t3 = new Thread3();
t3.setName("线程三");
t3.start();
}
}
12.3 多线程状态及常用方法
/*
* Copyright 2006-2021 webrx Group.
*/
package cn.webrx;
import java.util.concurrent.TimeUnit;
/**
*
*
*
*
* @author webrx [webrx@126.com]
* @version 1.0
* @date 2021-01-28 14:27:03
*/
public class Thread4 {
public static void main(String[] args) {
Thread t0 = new Thread(()->{
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
System.out.println(Thread.currentThread().getPriority());
},"ttt1");
t0.setName("ttt-000");
t0.setPriority(10);
t0.start();
//设置线程
Thread.currentThread().setName("主线程");
//设置优先级 1 - 10
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
try {
//Thread.sleep(10000);
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName());
System.out.println(Thread.currentThread().getPriority());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
12.3.1 多线程实现UDP聊天
/*
* Copyright 2006-2021 webrx Group.
*/
package cn.chat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
/**
*
*
*
*
* @author webrx [webrx@126.com]
* @version 1.0
* @date 2021-01-28 15:35:49
*/
public class One {
public static Set set = new HashSet();
public static void main(String[] args) {
String name = args[2];
String ip = args[0];
int port = Integer.parseInt(args[1]);
//接收
new Thread(() -> {
try {
DatagramSocket ds = new DatagramSocket(port);
DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);
while (true) {
ds.receive(dp);
String nip = dp.getAddress().getHostAddress();
set.add(nip);
System.out.println(nip+new String(dp.getData(), 0, dp.getLength(), "utf-8"));
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
//发线程 广播
new Thread(() -> {
Scanner sc = new Scanner(System.in);
try {
DatagramSocket ds = new DatagramSocket();
while (true) {
String msg = String.format("%s:%s [%3$tF %3$tT] - [ %4$d ]%n", name, sc.nextLine(), System.currentTimeMillis(),set.size());
byte[] data = msg.getBytes(StandardCharsets.UTF_8);
int len = data.length;
for (int i = 1; i System.out.println("hello"));
t.setName("t1");
t.setPriority(10);
t.start();
My my = new My();
my.start();
Thread t3 = new Thread(new User());
t3.start();
Thread t4 = new Thread(){
public void run() {
System.out.println("t444444444444444");
}
};
t4.start();
}
}
class User implements Runnable{
public void run() {
System.out.println("useruseruser");
}
}
class My extends Thread{
public void run() {
System.out.println("hello2222");
}
}
12.4 java多线程实现
12.4.1 多线程模拟售票
/*
* Copyright 2006-2021 webrx Group.
*/
package cn.exam;
import java.util.concurrent.TimeUnit;
/**
*
*
*
*
* @author webrx [webrx@126.com]
* @version 1.0
* @date 2021-01-29 10:35:33
*/
public class SellTicket {
public static void main(String[] args) {
Ticket t = new Ticket(50);
Thread t1 = new Thread(t,"科学大道");
Thread t2 = new Thread(t,"东风路");
Thread t3 = new Thread(t,"火车站");
Thread t4 = new Thread(t,"瑞达路");
t1.start();t2.start();t3.start();t4.start();
}
}
class Ticket implements Runnable {
private int num = 100;
public Ticket() {
}
public Ticket(int num) {
this.num = num;
}
public void run() {
while(true){
synchronized (this) {
if (num > 0) {
System.out.printf("[%s] 售出一张票,剩余%d张票%n", Thread.currentThread().getName(), --num);
} else {
System.out.printf("%n[%s] 票已售完,停止售票。", Thread.currentThread().getName());
break;
}
}
try{
TimeUnit.SECONDS.sleep(1);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
12.4.2 定时关机
/*
* Copyright (c) 2006, 2021, webrx.cn All rights reserved.
*
*/
package cn.exam;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* Project: part12 - MyClose
*
Powered By webrx
*
Created By IntelliJ IDEA On 2021-01-29 14:49:42
*
Description :
*
* @author webrx [webrx@126.com]
* @version 1.0
* @since 15
*/
public class MyClose {
public static void main(String[] args) {
//多长时间后关机 5m
new Thread(()->{
long t1 = System.currentTimeMillis();
while(true){
long ok = System.currentTimeMillis() - t1;
if(ok >= 5 * 1000) break;
}
System.out.println("系统正在关机5...");
}).start();
//
new Thread(()->{
try{
TimeUnit.SECONDS.sleep(10);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("系统正在关机10");
}).start();
//指定时间关机 2021-1-30 21:30:00
new Thread(()->{
String s = "2021-1-29 15:13:59";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
long end = 0;
try {
end = sdf.parse(s).getTime();
} catch (ParseException e) {
e.printStackTrace();
}
try{
TimeUnit.MILLISECONDS.sleep(end-System.currentTimeMillis());
}catch(Exception e){
e.printStackTrace();
}
System.out.printf("%s - 系统正在关机%n",s);
}).start();
}
}
12.5 多线程工具类
12.5.1 Timer TimerTask
/*
* Copyright (c) 2006, 2021, webrx.cn All rights reserved.
*
*/
package cn.exam;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;
/**
* Project: part12 - TimerTest
*
Powered By webrx
*
Created By IntelliJ IDEA On 2021-01-29 15:18:10
*
Description :
*
* @author webrx [webrx@126.com]
* @version 1.0
* @since 15
*/
public class TimerTest {
public static void main(String[] args) throws ParseException {
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
System.out.printf("%1$tF %1$tT%n",System.currentTimeMillis());
//t.cancel();
}
}, 5000,1000);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
t.schedule(new TimerTask() {
public void run() {
t.cancel();
}
},sdf.parse("2021-01-29 15:28:30"));
Timer t2 = new Timer();
TimerTask tt = new TimerTask() {
public void run() {
System.out.println("hello world Timer");
t2.cancel();
}
};
t2.schedule(tt,10000);
}
}
12.5.2 TimeUnit
java.util.concurrent.CountDownLatch
-
实现方法一 一个线程实现功能,一个线程统计
/* * Copyright (c) 2006, 2021, webrx.cn All rights reserved. * */ package cn.webrx; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; /** *
Project: part12 - Sync1 *
Powered By webrx *
Created By IntelliJ IDEA On 2021-01-29 16:36:55 *
Description : * * @author webrx [webrx@126.com] * @version 1.0 * @since 15 */ public class Sync2 { public static void main(String[] args) { MySync2 ms = new MySync2(); new Thread(() -> { for (int i = 1; i { System.out.println("t2"); while (!ms.count()) ; System.out.println("已经有五个了"); }, "t2").start(); } } class MySync2 { private volatile List list = new ArrayList(); public void add() { list.add("add" + list.size()); System.out.println(String.format("%d = %s", list.size(), list.get(list.size() - 1))); } public boolean count() { boolean f = false; if (list.size() >= 5) { System.out.println(Thread.currentThread().getName() + "线程启动"); f = true; } return f; } }
案例二
/* * Copyright (c) 2006, 2021, webrx.cn All rights reserved. * */ package cn.webrx; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * 是一个计数器,线程完成一个记录一个,计数器递减,只能只用一次 * //参数count为计数值 * public CountDownLatch(int count) { }; * 调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行 * public void await() throws InterruptedException { }; * 和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行 * public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; * 将count值减1 public void countDown() { }; * CountDownLatch CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue *
Project: untitled - Demo *
Powered by webrx On 2021-01-31 18:56:45 *
Created by IntelliJ IDEA * * @author webrx [webrx@126.com] * @version 1.0 * @since 15 */ public class Test{ static void m(){ for(int i=0;i{ System.out.println("收尾开始"); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } //latch.countDown(); System.out.println("真正程序的大结局"); },"END").start(); new Thread(Test::m,"t1").start(); new Thread(Test::m,"t2").start(); new Thread(Test::m,"t3").start(); new Thread(Test::m,"t4").start(); m(); System.out.println("main - 大结局"); } }
实现多个线程,有一个线程收尾工作 /* * Copyright (c) 2006, 2021, webrx.cn All rights reserved. */ package cn.thread; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** *
Project: part12 - T8 *
Powered By webrx *
Created By IntelliJ IDEA On 2021-02-01 10:46:15 *
Description : 实现多个线程,有一个线程收尾工作。 * * @author webrx [webrx@126.com] * @version 1.0 * @since 15 */ public class T8 { static CountDownLatch latch = new CountDownLatch(5); void work(){ for(int i=0;it.eat(6),"李四").start(); new Thread(()->t.eat(2),"张三丰").start(); new Thread(()->t.eat(12),"赵六").start(); } }
ReentrantLock常常对比着synchronized来分析,我们先对比着来看然后再一点一点分析。
(1)synchronized是独占锁,加锁和解锁的过程自动进行,易于操作,但不够灵活。ReentrantLock也是独占锁,加锁和解锁的过程需要手动进行,不易操作,但非常灵活。
(2)synchronized可重入,因为加锁和解锁自动进行,不必担心最后是否释放锁;ReentrantLock也可重入,但加锁和解锁需要手动进行,且次数需一样,否则其他线程无法获得锁。
(3)synchronized不可响应中断,一个线程获取不到锁就一直等着;ReentrantLock可以相应中断。
ReentrantLock好像比synchronized关键字没好太多,我们再去看看synchronized所没有的,一个最主要的就是ReentrantLock还可以实现公平锁机制。什么叫公平锁呢?也就是在锁上等待时间最长的线程将获得锁的使用权。通俗的理解就是谁排队时间最长谁先执行获取锁。
https://baijiahao.baidu.com/s?id=1648624077736116382&wfr=spider&for=pc
-
公平锁
ReentrantLock /* * Copyright (c) 2006, 2021, webrx.cn All rights reserved. * */ package cn.webrx; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** *
Project: untitled - T *
Powered by webrx On 2021-01-31 19:16:40 *
Created by IntelliJ IDEA *
* @author webrx [webrx@126.com] * @version 1.0 * @since 15 */ public class T { Lock lock = new ReentrantLock(); void m1(){ lock.lock(); for(int i=0; i关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?