java多线程

线程的创建

三种创建方式:继承thread类,实现runnable接口,实现callable接口。

1,创建一个类,继承thread类,然后重写方法。在主方法中,new出这个类,然后调用start方法。


public class TestDemo1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(i);

}
}

public static void main(String[] args) {
TestDemo1 te = new TestDemo1();
te.start();
for (int i = 0; i < 2000; i++) {
System.out.println("wo"+i);
}
}
}

这样两个方法是同时执行的。
=================================================================
实现runnable接口
实现接口要用implements这个关键字
大部分跟第一个方法一样,只有一个地方不一样,是在调用start方法是要new一个thread类
public class TestDemo3 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(i);

}
}

public static void main(String[] args) {
TestDemo1 te = new TestDemo1();
new Thread(te).start();
for (int i = 0; i < 2000; i++) {
System.out.println("wo"+i);
}
}
}
=======================================================
callable了解即可。
=====================================================
静态代理模式
真实对象和代理对象都要实现同一个接口。
代理对象要代理真实角色
好处是代理对象可以做很多真实对象不能做的事情。
真实对象可以做自己要做的事情。
public class StaticProxy {
public static void main(String[] args) {
You you = new You();

new WeddingCompany(new You()).HappyMarry();
//WeddingCompany wCompany = new WeddingCompany(you);
// wCompany.HappyMarry();
}
}
interface Marry{
void HappyMarry();
}
class You implements Marry{
@Override
public void HappyMarry() {
System.out.println("你要结婚了。");
}
}
class WeddingCompany implements Marry{
private Marry target;
//You target=new You();

public WeddingCompany(You tar) {
this.target = tar;
}

@Override
public void HappyMarry() {
before();

this.target.HappyMarry();

after();

}

private void after() {
System.out.println("后");
}

private void before() {
System.out.println("前");
}
}
===========================================================
lambda表达式
定义一个函数式接口,就是只有一个方法的接口。
public class Lambda {
public static void main(String[] args) {

ILike like = () -> {
System.out.println("i like");

};
like.lam();

}
}
interface ILike{
void lam();
}
===============================================================
线程停止
自己设定一个外部定义
public class TestStop implements Runnable{
private boolean flag = true;
@Override
public void run() {

int i=0;
while (flag){
System.out.println("thread"+i+++"个");
}
}
public void stop(){
this.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("main"+i);
if (i==900){
testStop.stop();
System.out.println("ting");

}

}
}
}
==========================================================

网络延时
模拟网络延时可以放大问题的发生性
public static void main(String[] args) {
Date date=new Date(System.currentTimeMillis());
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(date);
date = new Date(System.currentTimeMillis());
}
=================================================================
线程礼让
有可能成功,也可能不成功
public class TestDemo7 {
public static void main(String[] args) {
MyYield my = new MyYield();
new Thread(my,"1").start();
new Thread(my,"2").start();
}


}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始");
Thread.yield(); //这里就是线程礼让
System.out.println(Thread.currentThread().getName()+"停止");
}
}
===============================================================
线程强制执行join
public class TestJoin implements Runnable {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("vip"+i);

}

}

public static void main(String[] args) {
TestJoin joi=new TestJoin();
Thread th =new Thread(joi);
th.start();

for (int i = 0; i < 500; i++) {
if (i==200){
try {
th.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}


System.out.println("main"+i);

}
}


}
主线程跑到200的时候,run方法中的线程就会插队,然后跑完才会让主线程继续跑。
尽量少用这个方法。
=================================================================
线程的五个状态:NEW,RUNNABLE,BLOCKED,WAITING,TERMINATED

public class TestState {
    public static void main(String[] args) {


Thread thread = new Thread(()-> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}


}
System.out.println("////");
});
Thread.State state = thread.getState();
System.out.println(state);
thread.start();
state = thread.getState(); //得到线程状态
System.out.println(state); //打印线程状态
while (state!=Thread.State.TERMINATED){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
state=thread.getState();
System.out.println(state);
}


}

}

线程一旦进入死亡状态就不能再次启动了。
========================================================
线程优先级
可以通过设置线程的优先级来一定程度影响线程执行的先后顺序,线程优先级一共10级。
public class TestPriority {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"->"+Thread.currentThread().getPriority());
MyPriority myP = new MyPriority();
Thread t1= new Thread(myP);
Thread t2= new Thread(myP);
Thread t3= new Thread(myP);
Thread t4= new Thread(myP);

t1.setPriority(4);
t1.start();
t2.setPriority(6);
t2.start();
t3.setPriority(Thread.MAX_PRIORITY);
t3.start();
t4.setPriority(1);
t4.start();


}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"->"+Thread.currentThread().getPriority());
}
}

优先级高的不一定先跑,但是大多数情况下,优先级高的会先跑。
============================================================================
守护线程
虚拟机是不用等待守护线程执行完毕的。
等到用户线程执行完毕之后,守护线程自动也会执行完毕。
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
You2 you2 = new You2();

Thread thread = new Thread(god);
thread.setDaemon(true); //这里就是设置守护线程。
thread.start();
new Thread(you2).start();

}
}


class You2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 30000; i++) {
System.out.println("开心"+i);

}
System.out.println("goodbye");
}
}
class God implements Runnable{
@Override
public void run() {
int i =0;
while (true){
System.out.println("保佑"+i++);
}
}
}
 =================================================================
线程同步用
synchronized关键词来锁定对象,这样线程才不会挤到一起。找这个锁的对象一定要找对。
 
public class UBank {
public static void main(String[] args) {
Account accou = new Account();
accou.name="基金";
accou.money=100;
Draw you= new Draw(accou,50,"you");
Draw girl= new Draw(accou,100,"girl");
you.start();
girl.start();
 
}
class Account{
int money;
String name;
}
class Draw extends Thread{
Account acc;
int drawMon;


public Draw(Account acco, int drawMon1,String name) {
super(name);
this.acc = acco;
this.drawMon = drawMon1;


}

@Override
public void run() {
synchronized (acc) {
if (acc.money - drawMon < 0) {
System.out.println(this.getName() + "余额不足");
return;
}

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
acc.money = acc.money - drawMon;

System.out.println(acc.name + "余额" + acc.money);
System.out.println(this.getName() + drawMon);

}
}



}
----------------------------
public class BuyTicket {
public static void main(String[] args) {
BuyT sta = new BuyT();

new Thread(sta,"明").start();
new Thread(sta,"红").start();
new Thread(sta,"黄").start();
}
}
class BuyT implements Runnable{
private int num =10;
private boolean flag =true;

@Override
public void run() {
while (flag){
buy();
}

}
public synchronized void buy(){
if (num<=0){
flag=false;
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+num--);


}


}
=====================================================
死锁问题

import com.sun.deploy.security.SelectableSecurityManager;

public class Lock {
public static void main(String[] args) {
MakeUp g1 = new MakeUp(0, "灰姑娘");
MakeUp g2 = new MakeUp(1, "白雪公主");

g1.start();
g2.start();
}
}
class LipStick{

}
class Mirror {

}
class MakeUp extends Thread{

static LipStick lipStick=new LipStick();
static Mirror mirror=new Mirror();

int choice;
String girlName;

public MakeUp(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}

@Override
public void run() {
makeUp();
}
private void makeUp(){
if (choice==0){
synchronized (lipStick){
System.out.println(this.girlName+"lip");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror){
System.out.println(this.girlName+"mir");

}

}

}else{
synchronized (mirror){
System.out.println(this.girlName+"mir");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipStick){
System.out.println(this.girlName+"lip");

}


}

}

}
}


这样就会导致两个线程都在等待对方,从而无法继续,产生死锁。

import com.sun.deploy.security.SelectableSecurityManager;

public class Lock {
public static void main(String[] args) {
MakeUp g1 = new MakeUp(0, "灰姑娘");
MakeUp g2 = new MakeUp(1, "白雪公主");

g1.start();
g2.start();
}
}
class LipStick{

}
class Mirror {

}
class MakeUp extends Thread{

static LipStick lipStick=new LipStick();
static Mirror mirror=new Mirror();

int choice;
String girlName;

public MakeUp(int choice, String girlName) {
this.choice = choice;
this.girlName = girlName;
}

@Override
public void run() {
makeUp();
}
private void makeUp(){
if (choice==0){
synchronized (lipStick){
System.out.println(this.girlName+"lip");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

}
synchronized (mirror){
System.out.println(this.girlName+"mir");

}

}else{
synchronized (mirror){
System.out.println(this.girlName+"mir");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}

}
synchronized (lipStick){
System.out.println(this.girlName+"lip");

}

}

}
}
这样就不会产生死锁。
========================================
用reentrantlock类可以显示得添加锁。
import java.util.concurrent.locks.ReentrantLock;

public class BuyTicket {
public static void main(String[] args) {
BuyT sta = new BuyT();

new Thread(sta,"明").start();
new Thread(sta,"红").start();
new Thread(sta,"黄").start();
}
}
class BuyT implements Runnable{
private int num =10;
private boolean flag =true;

@Override
public void run() {

while (flag){

buy();
}


}

private final ReentrantLock lock=new ReentrantLock(); //定义一个锁,规范的写法是把锁放到try和finally里面。
public void buy(){


try {
lock.lock(); //加锁
if (num<=0){
flag=false;
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+num--);

} finally {
lock.unlock();//解锁

}


}

}
===============================================================
生产者消费者模型,利用缓冲区解决即管程法,利用缓冲区解决。利用等待(wait)和通知(notifyall)完成。
public class TestPC {
public static void main(String[] args) {
SynContainer Container = new SynContainer();
new Product(Container).start();
new Consumer(Container).start();
}
}
class Product extends Thread{
SynContainer container;
public Product(SynContainer 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{
SynContainer container;
public Consumer(SynContainer container){
this.container=container;

}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了-->"+container.eat().id+"只");

}
}

}
class Chicken {
int id;

public Chicken(int id) {
this.id = id;
}
}
class SynContainer {
Chicken[] chickens = new Chicken[10];
int count =0;

public synchronized void push(Chicken chi){
if (count==chickens.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}

}
chickens[count]=chi;
count++;
this.notifyAll();

}
public synchronized Chicken eat(){
if (count==0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}

}
count--;
Chicken chicken= chickens[count];
this.notifyAll();
return chicken;

}

}
=================================================================
信号灯发
public class TestPC2 {
public static void main(String[] args) {
TV tv0 = new TV();
new Player(tv0).start();
new Watcher(tv0).start();
}
}
class Player extends Thread{
TV tv2;

public Player(TV tv) {
this.tv2 = tv;
}

@Override
public void run() {
for (int i = 0; i < 20; i++) {
if (i%2==0){
this.tv2.play("王牌对王牌");
}else {
this.tv2.play("抖音");
}

}
}
}
class Watcher extends Thread{
TV tv1;

public Watcher(TV tv) {

this.tv1 = tv;



}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
tv1.watch();
}


}

}
class TV{
String voice;
boolean flag =true;
public synchronized void play(String voice1){
if (!flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

System.out.println("表演了" + voice1);
this.notifyAll();
this.voice = voice1;
this.flag = !this.flag;


}
public synchronized void watch() {
if (flag) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}

}

System.out.println("观看了" + voice);

this.notifyAll();
this.flag = !this.flag;

}

}
=========================================================
runnable和callable都有用线程池开启线程的方法,具体看视频。
posted @ 2021-03-06 11:57  即墨非音  阅读(75)  评论(0)    收藏  举报