Java基础 ---- ---- ---- 多线程
1.通过继承Thread类重写run()方法来实现多线程:(不推荐,因为Java单继承的局限性)
public class Thread_Many extends Thread {
long minParam;
public Thread_Many(long minParam) {
this.minParam = minParam;
}
public static void main(String[] args) {
Thread_Many thread_many0 = new Thread_Many(1);
Thread_Many thread_many1 = new Thread_Many(1);
thread_many0.start();
thread_many1.start();
for (int i = 0; i < 100 ; i++) {
System.out.println("Main : " + i);
}
}
@Override
public void run(){
for (int i = 0; i < 1000 ; i++) {
System.out.println(this.getId() + ":" + i);
}
}
}
//在Thread_Many中的三个线程分别是main线程、thread_many0、thread_many1三个线程并发执行,cpu轮到谁谁就执行,当多核时可以并行执行。
2.通过实现Runable接口来实现多线程:(推荐)
public class Many_Thread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100 ; i++) {
System.out.println("I like Java : " + i);
}
}
public static void main(String[] args) {
Many_Thread many_thread = new Many_Thread();
Many_Thread many_thread1 = new Many_Thread();
new Thread(many_thread).start();
new Thread(many_thread1).start();
for (int i = 0; i < 100; i++) {
System.out.println("Main : " + i);
}
}
}
龟兔赛跑多线程案例
import java.util.Random;
public class Rabbits implements Runnable {
private static Thread winner = null;
@Override
public void run() {
Random random = new Random();
for (int i = 1; i <= 100; i++) {
//判断是否有兔或有龟跑完
if (winner != null){
break;
}
int sign = random.nextInt(2);
//兔子睡
if (sign == 0 && Thread.currentThread().getName().equals("兔子")){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//兔子跑
if (sign == 1 && Thread.currentThread().getName().equals("兔子")){
i += 10;
}
System.out.println(Thread.currentThread().getName() + "跑了" + i + "步了");
if (i == 100){
winner = Thread.currentThread();
System.out.println(winner.getName() + "是获胜者");
}
}
}
public static void main(String[] args) {
Rabbits rabbits = new Rabbits();
// 开启两个线程
new Thread(rabbits,"兔子").start();
new Thread(rabbits,"乌龟").start();
}
}
静态代理与多线程:
//婚介中心代理结婚
package Marry;
public class ProxyMarry {
Marry marry = null;
public ProxyMarry(Marry marry) {
this.marry = marry;
}
//真实被代理的角色只需要做自己主要的功能,其余交给代理对象
public void MMarry(){
Before();
marry.marry();
After();
}
public void Before(){
System.out.println("布置现场");
}
public void After(){
System.out.println("收拾场地");
}
public static void main(String[] args) {
Marry one = new Marry("XXX");
ProxyMarry proxyMarry = new ProxyMarry(one);
//使用多线程执行不重要的部分,使得结婚的过程中还能说I love you等!
new Thread(() -> System.out.println("I love you!")).start();
proxyMarry.MMarry();
}
}
setPriority(int newPriority) //更改线程的优先
static void sleep(long millis) //令线程睡眠millis毫秒
static void yield() //暂停当前线程,使该线程变为就绪态,使cpu重新选择线程(有礼让成功与礼让失败之分,礼让失败表示cpu在此选择了该线程,礼让成功则表示cpu在该线程礼让后选择了其他线程)
void join() //使该线程执行完在执行其他线程,类似vip
boolean isAlive() //判断该线程是否处于活动状态
void setPriority(int Quan) //权重(1-10) 修改线程的权重,权重高的线程更容易被cpu执行
Thread.state getState() //获取该线程的状态,状态的种类如下图
1.使线程停止的方式:
public class XianCheng_Stop implements Runnable {
private Boolean flag = true;
@Override
public void run() {
int i = 0;
while (this.flag){
System.out.println("hello " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
}
//通过这个方法让重写的run方法中的死循环结束以达到停止线程的目的
public void stop(){
this.flag = false;
}
public static void main(String[] args) throws InterruptedException {
XianCheng_Stop xianCheng_stop = new XianCheng_Stop();
new Thread(xianCheng_stop).start();
for (int i = 0; i < 1000; i++) {
Thread.sleep(100);
if (i == 10){
xianCheng_stop.stop();
System.out.println("子线程执行结束!!");
}
System.out.println("main " + i);
}
}
}
2.守护线程(开启守护线程的方式)
XianCheng_Stop xianCheng_stop = new XianCheng_Stop();
Thread thread = new Thread(xianCheng_stop);
thread.setDaemon(true); //默认参数为false,false表示用户线程,true表示守护线程,jvm不会等待守护线程执行完
thread.start();
3.同步代码块
synchronized //放在方法上锁住的是this,也就是本身的类
synchronized(obj){} // 同步块可以锁任意对象
4.死锁
1.互斥条件:一个资源每次只能被一个进程使用;
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放;
3.不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺;
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系;
public class Lock extends Thread {
static Mirror mirror = new Mirror();
static Kouhong kouhong = new Kouhong();
//这里如果不设置为静态资源,那两个线程争夺的不是同一份资源,也就不会产生死锁
int choice = 0;
String person;
public Lock(int choice,String person) {
this.choice = choice;
this.person = person;
}
@Override
public void run() {
if (choice == 0){
//这里资源产生争夺,在拥有mirror时还要争夺kouhong,与下边相反
synchronized(mirror){
System.out.println(person + "拿到了镜子!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(kouhong){
System.out.println(person + "拿到了口红!");
}
}
}else {
//两个线程得到资源后都不释放,且去争夺对方的资源,出现死锁
synchronized(kouhong){
System.out.println(person + "拿到了口红!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(mirror){
System.out.println(person + "拿到了镜子!");
}
}
}
}
}
class My{
public static void main(String[] args) {
Lock b = new Lock(0, "白雪公主");
Lock x = new Lock(1, "小矮人");
new Thread(b).start();
new Thread(x).start();
}
}
class Mirror{}
class Kouhong{}
5.加锁(ReentranLock(可重入锁) && synchronized)
lock锁需要手动开关,synchronized出了作用域自动开锁。
lock锁只能锁代码块,synchronized有方法锁和代码块锁。
lock锁性能更好,可以使JVM花较少的时间来调度线程。
public static final ReentranLock lock = new ReentranLock();
import java.util.concurrent.locks.ReentrantLock;
public class Many_Thread implements Runnable {
private static tickets tickets;
public Many_Thread(tickets t) {
tickets = t;
}
//创建锁对象
private static final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
lock.lock(); // 加锁
if (tickets.ticket <= 10) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "拿到了第" + tickets.ticket + "张票");
tickets.ticket++;
}else{
break;
}
}finally {
lock.unlock(); //解锁
}
}
}
public static void main(String[] args) {
tickets tickets = new tickets(1);
Many_Thread many_thread = new Many_Thread(tickets);
new Thread(many_thread,"小沸").start();
new Thread(many_thread,"小美").start();
}
}
6.线程间的通信
1.锁对象.wait() //令该线程进入等待,释放锁
2.锁对象.wait(time) //毫秒
3.锁对象.notify() //表示通知并唤醒共享该资源对象的一个线程
4.锁对象.notifyAll() //表示通知并唤醒共享该资源对象的所有线程
以下代码出现死锁问题,暂未解决。如有解决方案,还望私信(感谢)
import java.util.ArrayList;
import java.util.HashMap;
public class ticket_all {
public static void main(String[] args) {
huanchong huanchong = new huanchong();
new shengchan(huanchong).start();
new xiaofei(huanchong).start();
}
}
//票对象
class tick{
int id;
public tick(int id) {
this.id = id;
}
}
class huanchong{
static ArrayList<tick> map = new ArrayList<>();
public void push(tick t) throws InterruptedException {
synchronized (map) {
while (map.size() == 10) {
map.wait(1000);
}
System.out.println(t.id + "新票已经准备好了");
map.add(t);
map.notifyAll();
}
}
public void get() throws InterruptedException {
synchronized (map) {
while (map.size() == 0) {
map.wait(1000);
}
System.out.println(Thread.currentThread().getName() + "获得第" + map.get(map.size() - 1).id + "票");
map.remove(map.size() - 1);
map.notifyAll();
}
}
}
//生产票的对象
class shengchan extends Thread{
huanchong huanchong;
public shengchan(huanchong huanchong) {
this.huanchong = huanchong;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
if (i % 2 == 0 && huanchong.map.size() != 10){
try {
huanchong.push(new tick(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
//买票的对象
class xiaofei extends Thread{
huanchong huanchong;
public xiaofei(huanchong huanchong) {
this.huanchong = huanchong;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
try {
huanchong.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
7.线程池
ExecutorService es = Executors.newFixedThreadPool(x) //x表示线程池中线程的个数
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class XianChengPool {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new one()); //执行一个线程
executorService.execute(new one());
executorService.execute(new one());
executorService.execute(new one());
executorService.shutdown(); //关闭线程池
}
}
class one implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName() +" "+ i);
}
}
}