首先了解下线程的状态
微信图片_20210513144401.png
继承方式实现
package ThreadTest;
/**
* Created by kumamon on 2021/5/13.
*/
public class ThreadDemo {
public static void main(String[] args) {
MythreadDemo mythreadDemo = new MythreadDemo();
mythreadDemo.start();
}
}
class MythreadDemo extends Thread{
@Override
public void run() {
System.out.println("使用 extends Thread 来创建线程");
}
}
Ruannable方式(推荐使用,因为java是单继承,这种方式还可以有父类)
package ThreadTest;
/**
* Runnable
* 直接使用 extends Thread 的方式 不能实现多继承
* 使用这种方式可以继续继承其他的类
* 解耦
*
* Created by kumamon on 2021/5/12.
*/
public class Runnable {
public static void main(String[] args) {
Thread thread=new Thread(new MyRunnableMain());
thread.start();
}
}
class MyRunnableMain implements java.lang.Runnable {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+ i);
}
}
}
线程守护
package ThreadTest;
/**
* 守护线程
* 一个线程设置为守护线程后,当被守护的线程退出了,那么自己的线程也就退出
*
* main里面只能创建一个唯一的线程,要么守护线程不起效
* Created by kumamon on 2021/5/13.
*/
public class Thread_Deamon {
public static void main(String[] args) throws InterruptedException {
T1 t1 = new T1();
t1.setDaemon(true); //T1 设置为main的守护线程 ,当main线程结束后,T1也跟着结束
t1.start();
//T2 t2 = new T2();
//t2.start(); // T2没有设置,main 线程结束后,T2还在执行,等T2结束后,进程停止
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println("主线程 正在执行");
}
System.out.println("主线程执行完毕,退出");
}
}
class T1 extends Thread {
@Override
public void run() {
for (;;) { //死循环
try {
Thread.sleep(1000);
System.out.println("子线程 1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class T2 extends Thread {
@Override
public void run() {
for (;;) { //死循环
try {
Thread.sleep(1000);
System.out.println("子线程 2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程加入和让出
package ThreadTest;
/**
* Created by kumamon on 2021/5/13.
*/
public class Thread_Join_Yield {
public static void main(String[] args) {
Thread thread=new T();
thread.start();
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"正在吃"+i+"包子");
if(i==5){
/**
* 线程加入。
* 主线程在执行过程中, 让 子线程先执行
*
@System.out.println("子线程加入先吃包子");
@thread.join();
* */
/**
* 线程礼让。(是执行自己礼让)
* 主线程在执行过程中, 让子线程先执行
* 这种方式不一定成功,取决于电脑的CPU调度
@System.out.println("自己礼让,让子线程先吃");
@Thread.yield();
* */
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class T extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(1000);
System.out.println(this.getName()+"正在吃"+i+"包子");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
不同步的线程(数据不合理)
package ThreadTest;
/**
* 窗口同时在卖一张票, 还卖了不存的票,(数据不合理)
* 相当于 3个人在同一时间上同一个厕所
* <p>
* Created by kumamon on 2021/5/12.
*/
public class Thread_No_Synchronized {
public static void main(String[] args) {
MyRunnable1 myRunnable = new MyRunnable1();
Thread thread1 = new Thread(myRunnable, "窗口1");
Thread thread2 = new Thread(myRunnable, "窗口2");
Thread thread3 = new Thread(myRunnable, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class MyRunnable1 implements java.lang.Runnable {
int sum = 100;
@Override
public void run() {
while (true) {
if (sum > 0) { //判断票数还有多少张呢
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
sum--;
}
}
}
}
同步代码块(数据合理) 还是上面的例子,不会出现-1 张票
package ThreadTest;
/**
* 使用 Synchronized 前提是多个线程 访问同一个数据 (线程安全)
* 相当于 3个人在同一时间上同一个厕所
* 但是只能一个一个来,一个上完另一个在上
* <p>
*
*
* 原理就是 jvm在运行时会检测这个锁的对象属于那个线程
* 这样争抢的过程中,只能有锁对象的执行
*
*
* Synchronized 包含的是 访问同一数据的代码
*
* Created by kumamon on 2021/5/12.
*/
public class Thread_Synchronized_Object {
public static void main(String[] args) {
MyRunnable4 myRunnable = new MyRunnable4();
Thread thread1 = new Thread(myRunnable, "窗口1");
Thread thread2 = new Thread(myRunnable, "窗口2");
Thread thread3 = new Thread(myRunnable, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class MyRunnable4 implements java.lang.Runnable {
int sum = 100; //票数
Object obj = new Object(); //设置锁 对象为Object 可以为任意的
@Override
public void run() {
synchronized (obj) {
while (sum > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
sum--;
}
}
}
}
同步方法(数据安全)
package ThreadTest;
/**
* 使用同步方法(数据安全)
* 和
* 相当于 3个人在同一时间上同一个厕所
* 但是只能一个一个来,一个上完另一个在上
* <p>
* Created by kumamon on 2021/5/12.
*/
public class Thread_Synchronized_Method {
public static void main(String[] args) {
MyRunnable2 myRunnable = new MyRunnable2();
Thread thread1 = new Thread(myRunnable, "窗口1");
Thread thread2 = new Thread(myRunnable, "窗口2");
Thread thread3 = new Thread(myRunnable, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class MyRunnable2 implements java.lang.Runnable {
int sum = 100; //票数
Object obj = new Object(); //设置锁 对象为Object 可以为任意的
@Override
public void run() {
pay();
/**
* 等同于如下代码 不过obj 是 MyRunnable 而已就是this
synchronized (obj) {
while (sum > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
sum--;
}
}
*/
}
private synchronized void pay(){
while (sum > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
sum--;
}
}
}
静态同步方法
package ThreadTest;
/**
* 使用 Synchronized 前提是多个线程 访问同一个数据 (线程安全)
* 相当于 3个人在同一时间上同一个厕所
* 但是只能一个一个来,一个上完另一个在上
*
* 这种一般来保证 单例模式 的线程安全
*
*
* <p>
* Created by kumamon on 2021/5/12.
*/
public class Thread_Synchronized_Method_Static {
public static void main(String[] args) {
MyRunnable3 myRunnable = new MyRunnable3();
Thread thread1 = new Thread(myRunnable, "窗口1");
Thread thread2 = new Thread(myRunnable, "窗口2");
Thread thread3 = new Thread(myRunnable, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class MyRunnable3 implements java.lang.Runnable {
static int sum = 100; //票数
@Override
public void run() {
payStatic();
}
private static synchronized void payStatic(){ //此处的锁是 MyRunnable3 .class 不是this对象
while (sum > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
sum--;
}
}
}
Lock锁同步
package ThreadTest;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 使用 Lock 前提是多个线程 访问同一个数据 (线程安全)
* 相当于 3个人在同一时间上同一个厕所
* 但是只能一个一个来,一个上完另一个在上
* <p>
* <p>
*
* 使用方式
*
* 创建Lock 对象
* Lock lock = new ReentrantLock();
*
* 在访问共享数据前
*
* lock.lock();
* ***
* *访问共享数据代码
* ***
* lock.unlock();
*
* 建议增加try 这样无论这次操作是否有异常 都会释放,让下一个线程访问
*
* Created by kumamon on 2021/5/12.
*
*
*/
public class Thread_Lock {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread1 = new Thread(myRunnable, "窗口1");
Thread thread2 = new Thread(myRunnable, "窗口2");
Thread thread3 = new Thread(myRunnable, "窗口3");
thread1.start();
thread2.start();
thread3.start();
}
}
class MyRunnable implements java.lang.Runnable {
int sum = 100; //票数
Lock lock = new ReentrantLock();
@Override
public void run() {
lock.lock();
try {
while (sum > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
sum--;
}
} finally {
lock.unlock();
}
}
}
线程死锁
- 线程死锁是指两个或两个以上的线程互相持有对方所需要的资源,
- 由于synchronized的特性,一个线程持有一个资源,或者说获得一个锁,
- 在该线程释放这个锁之前,其它线程是获取不到这个锁的,
- 而且会一直死等下去,因此这便造成了死锁。
package ThreadTest;
/**
*
* 线程死锁是指两个或两个以上的线程互相持有对方所需要的资源,
* 由于synchronized的特性,一个线程持有一个资源,或者说获得一个锁,
* 在该线程释放这个锁之前,其它线程是获取不到这个锁的,
* 而且会一直死等下去,因此这便造成了死锁。
*
*
* Created by kumamon on 2021/5/13.
*/
public class ThreadDead {
public static void main(String[] args) {
MyThreadDead threadA = new MyThreadDead(true);
MyThreadDead threadB = new MyThreadDead(false);
threadA.start();
threadB.start();
}
}
class MyThreadDead extends Thread{
boolean flag=true;
public static Object o1= new Object();
public static Object o2 =new Object();
public MyThreadDead(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
if(flag){
synchronized (o1){
System.out.println("A线程持有了 o1的对象锁,未执行完 不释放 o1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o2){
System.out.println("A线程");
}
}
}else{
synchronized (o2){
System.out.println("B线程持有了 o2的对象锁,未执行完 不释放 02");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o1){
System.out.println("B线程");
}
}
}
}
}
线程通讯
package ThreadTest;
/**
* Created by kumamon on 2021/6/3.
* <p>
* 模拟
* 观众看电视
* 演员录电视
*/
public class Thread_TongXun {
public static void main(String[] args) {
TV tv = new TV();
new Yanyuan(tv).start();
new Guanzhong(tv).start();
}
}
class Yanyuan extends Thread {
TV tv;
public Yanyuan(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
tv.yan();
}
}
}
class Guanzhong extends Thread {
TV tv;
public Guanzhong(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
tv.kan();
}
}
}
class TV {
boolean flag = false; //设置标志位,什么时候演员录 什么时候观众看
public synchronized void yan() {
//等待观众看完的通知
if (flag) { //演员录
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("演员录完电视,通知观众看电视");
this.flag = !this.flag;
this.notifyAll();//通知观众
}
public synchronized void kan() {
if (!flag) { //观众看
//等待 演员录完电视的通知
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观众看完了电视-----通知演员继续录");
this.flag = !this.flag;
this.notifyAll();
}
}
image.png
网友评论