程序是指令和数据的有序集合,起本升本没有任何运行的含义,是一个静态的概念
进程是执行程序的一次执行过程,他是一个动态的概念,是系统资源分配的单位
通常在一个进程中,可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义,线程是cpu调度和执行的单位
继承Thread类(重点)
//创建线程方式1:继承Thread类,重写run,调用start开启线程
public class TestThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("-----");
}
}
public static void main(String[] args) {
//创建一个线程对象
TestThread1 testThread1 = new TestThread1();
//调用start方法,开启线程
testThread1.start();
//main线程,主线程
for (int i = 0; i < 20; i++) {
System.out.println("主线程");
}
}
}
//两个线程是同时执行的,线程开启后不一定立即执行,按照cpu安排调度
实现图片同步下载
package org.example;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.rmi.Naming;
//实现多线程同步下载图片
public class TestThread2 extends Thread{
private String url;
private String path;
public TestThread2(String url,String name){
this.url =url;
this.path =name;
}
@Override
public void run() {
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url, path);
System.out.println("下载了文件名为:"+path);
}
public static void main(String[] args) {
String url ="https://img-blog.csdnimg.cn/3199ad8ae6974b33953faa7a233a763a.png";
String path = "test.jpg";
TestThread2 t1 = new TestThread2(url, path);
TestThread2 t2 = new TestThread2("https://img-blog.csdnimg.cn/cd63b3bdaa6d4c468238922c197bd2f7.png", "2.jpg");
TestThread2 t3 = new TestThread2("https://img-blog.csdnimg.cn/ae7b9b2c89fb4069802660a4d6bbd691.png", "3.jpg");
t1.start();
t2.start();
t3.start();
}
}
class WebDownloader{
public void downloader(String url, String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
}
}
}
实现Runnable接口(重点)
package org.example;
public class TestRunnable1 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("多线程启动");
}
}
public static void main(String[] args) {
TestRunnable1 testRunnable1 = new TestRunnable1();
new Thread(testRunnable1).start();
for (int i = 0; i < 30; i++) {
System.out.println("主线程");
}
}
}
package org.example;
//龟兔赛跑
public class Race implements Runnable{
private String winner;
@Override
public void run() {
for (int i = 0; i <=100; i++) {
if(Thread.currentThread().getName().equals("兔子") && i %10 ==0){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if(gameOver(i)) break;
System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
gameOver(i);
}
}
private boolean gameOver(int step){
if(winner != null){
return true;
}else {
if(step == 100){
winner = Thread.currentThread().getName();
System.out.println("winer is " +winner);
return true;
}
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
实现Callable接口(了解)
代理对象可以做额外的事情
真实对象只需要做要做的事情
package org.example;
//静态代理模式:真实对象和代理对象都要实现同一个接口,代理对象要代理真实角色,
public class StaticProxy {
public static void main(String[] args) {
Person person = new Person();
WeddingCompany weddingCompany = new WeddingCompany(person);
weddingCompany.marry();
}
}
interface Marry{
void marry();
}
class Person implements Marry{
@Override
public void marry() {
System.out.println("要结婚了超开心");
}
}
class WeddingCompany implements Marry{
private Marry target;
public WeddingCompany(Marry target){
this.target =target;
}
@Override
public void marry() {
before();
this.target.marry();
after();
}
private void after() {
System.out.println("结婚之后收尾款");
}
private void before() {
System.out.println("结婚前布置现场");
}
}
package org.example;
import jdk.internal.org.objectweb.asm.tree.analysis.SourceInterpreter;
public class TestStop implements Runnable{
private boolean flag =true;
@Override
public void run() {
while (flag){
System.out.println("线程在执行");
}
}
public void stop(){
flag = false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 1000; i++) {
System.out.println(i);
if( i== 900){
testStop.stop();
System.out.println("线程停止了" );
break;
}
}
}
}
sleep(time) 毫秒
存在InterruptedException
sleep可以模拟网络延迟倒计时
每个对象都有锁,sleep不会释放锁
package org.example;
public class TestYield {
public static void main(String[] args) {
myYield myYield = new myYield();
new Thread(myYield,"a").start();
new Thread(myYield,"b").start();
}
}
class myYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程停止执行");
}
}
Join线程合并,待此线程执行完成后,再执行其他线程,其他线程阻塞
package org.example;
public class TestJoin {
public static void main(String[] args) {
MyJoin myJoin = new MyJoin();
Thread thread = new Thread(myJoin);
thread.start();
for (int i = 0; i < 500; i++) {
if(i ==200){
try {
thread.join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("main"+i);
}
}
}
class MyJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("线程vip来了"+i);
}
}
}
package org.example;
public class TestStatus {
public static void main(String[] args) {
Thread r = new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
System.out.println("---");
} catch (InterruptedException e) {
}
}
});
System.out.println(r.getState());
r.start();
System.out.println(r.getState());
}
}
先设置优先级在启动,大的先执行,但是还是由cpu决定
package org.example;
public class TestPriority {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+" "+Thread.currentThread().getPriority());
Thread t1 = new Thread(new myPriority());
Thread t2 = new Thread(new myPriority());
Thread t3 = new Thread(new myPriority());
t1.start();
t2.setPriority(1);
t2.start();
t3.setPriority(8);
t3.start();
}
}
class myPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" "+Thread.currentThread().getPriority());
}
}
package org.example;
public class TestDaemon {
public static void main(String[] args) {
god god = new god();
You you = new You();
Thread thread = new Thread(god);
//设置守护县城
thread.setDaemon(true);
thread.start();
new Thread(you).start();
}
}
class god implements Runnable{
@Override
public void run() {
while (true){
System.out.println("上帝保佑着你");
}
}
}
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("happy everyDay");
}
System.out.println("goodBye world");
}
}
多个线程操作同一个资源
不安全
package syn;
import sun.rmi.runtime.NewThreadAction;
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket,"1").start();
new Thread(buyTicket,"2").start();
new Thread(buyTicket,"3").start();
new Thread(buyTicket,"4").start();
}
}
class BuyTicket implements Runnable{
private int ticket =10;
private boolean flag = true;
@Override
public void run() {
while (flag){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
buy();
}
}
private void buy(){
if(ticket <= 0) {
stop();
return;
}
System.out.println(Thread.currentThread().getName()+"拿到第"+ticket--+"张票");
}
public void stop(){
flag =false;
}
}
使用synchronized
synchronized方法控制对"对象的访问",每个对象对应一把锁,每个sync方法都必须获得调用该方法的对象的锁才能执行,否则会线程阻塞
方法一旦执行,就独占该锁,直到该方法返回才释放锁,后面被阻塞的线程才能获得这个锁,继续执行
package syn;
public class UnsafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
new Thread(buyTicket,"1").start();
new Thread(buyTicket,"2").start();
new Thread(buyTicket,"3").start();
new Thread(buyTicket,"4").start();
}
}
class BuyTicket implements Runnable{
private int ticket =10;
private boolean flag = true;
@Override
public void run() {
while (flag){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
buy();
}
}
private synchronized void buy(){
if(ticket <= 0) {
stop();
return;
}
System.out.println(Thread.currentThread().getName()+"拿到第"+ticket--+"张票");
}
public void stop(){
flag =false;
}
}
sycn(obj){}
obj称之为同步监视器
同步监视器执行过程
package syn;
import java.util.ArrayList;
public class UnSafeList {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(list.size());
}
}
juc下的线程安全集合
package syn;
import java.util.concurrent.CopyOnWriteArrayList;
public class TestJUC {
public static void main(String[] args) {
//测试juc安全数组
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
for (int i = 0; i < 1000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(list.size());
}
}
多个线程各自占有一些共享资源,并且互相等待其他线程占有的支援才能运行,而导致两个或多个线程都在等待对方释放资源,都停止执行的 场景,某个同步块同时拥有"两个以上对象的锁"时就有可能会发生死锁问题.
package syn;
//死锁:多个线程互相占有对方的支援,形成僵持
public class Lock {
public static void main(String[] args) {
MakeUp m1= new MakeUp(0, "1");
MakeUp m2= new MakeUp(0, "2");
m1.start();
m2.start();
}
}
//口红
class Lipstick{}
//镜子
class Mirror{}
class MakeUp extends Thread{
static Lipstick lipstick =new Lipstick();
static Mirror mirror = new Mirror();
int choice;
String girlName;
MakeUp(int choice,String girlName){
this.choice = choice;
this.girlName = girlName;
}
@Override
public void run() {
//化妆
try {
makeup();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
//互相拿到对方的锁
private void makeup() throws InterruptedException {
if(choice == 0){
synchronized (lipstick){
System.out.println(this.girlName+"获得口红的锁");
Thread.sleep(5000);
synchronized (mirror){
System.out.println("获得镜子的锁");
}
}
}else {
synchronized (mirror){
System.out.println(this.girlName+"获得口红的锁");
Thread.sleep(4000);
synchronized (lipstick){
System.out.println("获得镜子的锁");
}
}
}
}
}
package gaoji;
import java.util.concurrent.locks.ReentrantLock;
//测试lock
public class TestLock {
public static void main(String[] args) {
testLock2 t2 = new testLock2();
new Thread(t2).start();
new Thread(t2).start();
new Thread(t2).start();
}
}
class testLock2 implements Runnable{
int tickNum =10;
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true){
try {
//放到try里面
lock.lock();
if(tickNum >0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(tickNum--);
}else {
break;
}
}finally {
//一般写到finally
lock.unlock();
}
}
}
}
Java提供了几个方法解决线程之间的通信问题
package gaoji;
//测试生产者消费者模型
public class TestPC {
public static void main(String[] args) {
SyncContainer syncContainer = new SyncContainer();
Producer producer = new Producer(syncContainer);
Consumer consumer = new Consumer(syncContainer);
producer.start();
consumer.start();
}
}
class Producer extends Thread{
SyncContainer container;
public Producer(SyncContainer container){
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
container.push(new Chicken(i));
System.out.println("生产了"+i+"只鸡");
}
}
}
class Consumer extends Thread{
SyncContainer container;
public Consumer(SyncContainer container){
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了第"+container.pop());
}
}
}
class Chicken{
int id;
public Chicken(int id) {
this.id = id;
}
@Override
public String toString() {
return "Chicken{" +
"id=" + id +
'}';
}
}
//缓冲区
class SyncContainer{
Chicken[] chickens = new Chicken[10];
//容器计数器
int cnt = 0;
//生产者放入产品
public synchronized void push(Chicken product) {
if (cnt == 10) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
chickens[cnt] = product;
cnt++;
this.notifyAll();
}
public synchronized Chicken pop() {
if (cnt == 0) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
cnt--;
Chicken product = chickens[cnt];
this.notifyAll();
return product;
}
}
提前创建好多个线程,放入线程池,使用时直接获取,使用完放回池中
package gaoji;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPool {
public static void main(String[] args) {
//创建线程池,参数为大小
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new myThread());
executorService.execute(new myThread());
executorService.execute(new myThread());
executorService.execute(new myThread());
}
}
class myThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
roduct;
}
}
## 线程池
提前创建好多个线程,放入线程池,使用时直接获取,使用完放回池中
[外链图片转存中...(img-4V6tDQBC-1702542956181)]
[外链图片转存中...(img-9qAWm6xK-1702542956181)]
```java
package gaoji;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPool {
public static void main(String[] args) {
//创建线程池,参数为大小
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new myThread());
executorService.execute(new myThread());
executorService.execute(new myThread());
executorService.execute(new myThread());
}
}
class myThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}