1.线程和进程的概述
1.1什么是进程
正在执行的程序,称为进程。 进程是系统分配资源的单元。
1.2什么是线程
线程又称轻量级的进程,是CPU调度的基本单位,一个进程由一个或多个线程组成
进程与进程之间无法共享数据
同一个进程的线程与线程之间可以共享数据
2.并发与并行的概述
并行:2个或多个事件在同一时刻发生(同时发生 同时处理 执行者不是一个)
并发:2个或多个事件在同一时间段内发生(交替发生 执行者是一个)
3.为何使用多线程
为了提高cpu的使用率,提高的程序的效率。
4.java如何实现多线程任务
1. 继承Thread类
2.实现Runnable接口
3.实现Callable接
4.1Thread实现多线程
1.创建一个类继承Thread,重写run方法
2.创建线程并开启线程
public class MyThread { public static void main(String[] args) { Test01 t1=new Test01(); t1.start();//开启线程,默认调用run()方法 for (int i = 0; i < 20; i++) { System.out.println("main"+i); } } } class Test01 extends Thread{ @Override public void run(){ for (int i = 0; i < 20; i++) { System.out.println("线程"+i); } } }
4.2.Runnable实现多线程
1.创建一个类实现Runnable接口
public class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("线程"+i);
}
}
}
2.创建一个测试类,先创建任务对象,再创建线程对象,并把任务对象交予线程对象,再开启线程,最后创建一个主函数的线程,模拟多线程
public class Test01 { public static void main(String[] args) { //创建任务对象 MyRunnable my=new MyRunnable(); //创建线程对象,把任务对象交予线程对象 Thread t=new Thread(my); t.start(); for (int i = 0; i < 20; i++) { System.out.println("main"+i); } } }
4.3.Callable实现多线程
1.创建一个类实现Callable接口
public class MyCall implements Callable<Integer> { @Override public Integer call() throws Exception { int sum=0; for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+i); sum+=i; } return sum; } }
2.创建任务对象,并将任务对象封装进FutureTask,创建线程对象 task交予线程对象,开启线程
public class Test01C { public static void main(String[] args) throws ExecutionException, InterruptedException { //创建任务对象 MyCall m=new MyCall(); //将任务对象封装进FutureTask FutureTask task=new FutureTask<>(m); //创建线程对象,task交予线程对象 Thread t=new Thread(task); t.start(); for (int i = 0; i < 20; i++) { Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+i); } System.out.println(task.get()); } }
4.4三种创建多线程的使用场景
1、继承Thread的方式:适合于这个任务只想被一个线程的对象执行的情况
2、实现Runnable接口方式:适合于一个任务想被多个线程执行的情况 卖票
3、实现Callable接口方式:也适合一个任务想被多个线程执行的情况,并且想得倒任务的执行结果
5.Thread里面常用的方法
5.1start()
开启线程,而且该方法只能调用一次。
5.2run()
线程开启后,获取cpu时间片后 执行的任务方法。
5.3设置或获取线程名
setName("")
getName()
getName()只能在Thread子类下使用 Thread.currentThread().getName()可以在任何位置使用
5.4休眠sleep
public class TestSleep { public static void main(String[] args) { My my=new My(); my.start(); for (int i = 0; i < 20; i++) { System.out.println("main"+i); } } } class My extends Thread{ @Override public void run(){ for (int i = 0; i < 20; i++) { try { Thread.sleep(1000);//单位毫秒 } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("......."+i); } } }
5.5放弃yield
当前线程主动放弃时间片,回到就绪状态,竞争下一次时间片
public class My extends Thread{ @Override public void run() { for (int i = 0; i < 20; i++) { Thread.yield(); System.out.println(Thread.currentThread().getName()+i); } } }public class Test01My { public static void main(String[] args) throws InterruptedException { My my=new My(); my.setName("my线程a----------"); My my2=new My(); my2.setName("线程b-----------"); my.start(); my2.start(); } }
5.6加入join
允许其他线程加入到当前线程中,直到其他线程执行完毕后,当前线程才会执行。
public class Test01My { public static void main(String[] args) throws InterruptedException { My my=new My(); my.setName("my线程a----------"); My my2=new My(); my2.setName("线程b-----------"); my.start(); my2.start(); my.join(); my2.join(); for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+i); } } }
5.7setPriority设置优先级
public class TestPrority { public static void main(String[] args) { My04 my=new My04("a"); My04 my2=new My04("b"); My04 my3=new My04("c"); my.setPriority(Thread.MAX_PRIORITY); my2.setPriority(Thread.NORM_PRIORITY); my3.setPriority(Thread.MIN_PRIORITY); my.start(); my2.start(); my3.start(); } } class My04 extends Thread{ public My04(String name){ super(name); } @Override public void run(){ for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+"......."+i); } } }
5.8守护线程
线程对象. setDaemon(true)设置为守护线程。
线程有两类:用户线程(前台线程)和守护线程(后台线程)
如果程序中所有前台线程都执行完毕了,后台线程也会自动结束。
垃圾回收线程属于守护线程。
public class TestDeamon { public static void main(String[] args) { My05 my05=new My05(); //设置my05为守护线程,后台执行完毕,守护线程也结束 my05.setDaemon(true); my05.start(); for (int i = 0; i < 20; i++) { System.out.println("main"+i); } } } class My05 extends Thread{ @Override public void run(){ for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName()+"......."+i); } } }
6.卖票
某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票。
package com.ghx.demo11301;
/**
* @author :guo
* @date :Created in 2025/1/13 14:55
* @description:
* @modified By:
* @version:
*/
public class SellTicket implements Runnable{
private int tickets=100;
@Override
public void run() {
while (tickets > 0) {
tickets--;
System.out.println(Thread.currentThread().getName() + "卖了一张票,还剩" + tickets+"张");
}
}
}
package com.ghx.demo11301;
/**
* @author :guo
* @date :Created in 2025/1/13 14:57
* @description:
* @modified By:
* @version:
*/
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket sellTicket=new SellTicket();
Thread t=new Thread(sellTicket,"窗口a");
Thread t2=new Thread(sellTicket,"窗口b");
Thread t3=new Thread(sellTicket,"窗口c");
t.start();
t2.start();
t3.start();
}
}
出现的问题
重卖,超卖的线程安全问题
标签:java,Thread,void,class,线程,new,多线程,public From: https://blog.csdn.net/weixin_51635918/article/details/145110368