JAVA多线程学习详细总结

什么是线程和进程?

进程:
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。
在java中,当我们启动main函数时就是启动了一个JVM的进程,而main函数所在的线程就是这个进程中的一个线程,也称主线程。

线程:
线程和进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行过程中可以产生多个线程。
在java中,当我们启动main函数时其实就是启动了一个JVM的进程,而main函数所在的线程就是在这个进程的一个线程,也称为主线程。

使用多线程

1.继承Thread类,重写run方法。

public class Tiket2 extends Thread {
	private int i = 10;
	@Override
	public void run() {
		while (i > 0) {
			System.out.println("子线程..."+ i);
			i--;
		}
	}
}

测试类:

public class TiketTest {
	public static void main(String[] args) {
		Tiket2 tiket2 = new Tiket2();
		tiket2.start();
		System.out.println("主线程...");
	}
}

测试结果:
在这里插入图片描述
从这里我们可以看出先执行了main函数中的代码然后再执行的tiket2中的代码。
2.实现Runable接口

public class MyThread implements Runnable {
	private int i = 10;

	@Override
	public void run() {
		while (true) {
			if (i > 0) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "   " + i);
				i--;
			} else {
				break;
			}
		}
}

测试类:

public class MyThreadTest {
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		Thread thread = new Thread(myThread);
		thread.start();
	}
}

虽然MyThread实现了run的方法,但是创建的类并不能直接调用start的方法,需要new一个Thread类然后将创建的myThread放入参数中,最后通过thread来调用start方法。

解决多线程同步问题

我们模拟一个卖票的场景,总共有2个窗口一共有100张票,2个窗口同时卖票,如果线程不同步,那么可能就会造成2个窗口卖同一张票的情况,这样就会造成了线程不同步的问题。
我们创建一个TiketRunable实现了Runnable接口中的run方法:

public class TiketRunable implements Runnable {
    private int i = 100;
    @Override
    public void run() {
        //线程同步 锁
        while (true) {
//            synchronized (this) {
                if(i>0){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //t2
                    System.out.println(Thread.currentThread().getName() + "--" + i);
                    i--;
                }else {
                    break;
                }
//            }
        }
    }
}

测试类:

public class TiketRunableTest {
    public static void main(String[] args) {
        TiketRunable tiketRunable  = new TiketRunable();
        Thread thread =  new Thread(tiketRunable);
        Thread thread2 =  new Thread(tiketRunable);
        thread.start();
        thread2.start();
        System.out.println("main-end");
    }
}

测试结果:
在这里插入图片描述
从这里我们可以看出两个线程交替进行卖票,但是并没有解决线程冲突的问题,比如Thread0和Thread1同时卖了同一张票。所以我们解决线程同步的方法是加一个锁使用synchronized关键字。
使用synchronized关键字可以加在方法上面也可以加在代码块中,上面的代码被我注释掉了,这种方法就是加在代码块中,然后加在方法中的是:

public class TiketRunable implements Runnable {
    private static int i = 1000;
    @Override
    public void run() {
        //线程同步 锁
        while (true) {
            test();
             if (i<1) {
            	break;
            }
        }
    }
    public static synchronized void test() {
    	if(i>0){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //t2
            System.out.println(Thread.currentThread().getName() + "--" + i);
            i--;
        }else {
            return;
        }
    }
}

直接在方法中加上synchronized即可。
这两种方法是解决多线程同步的常用方法,还有一些不常用的方法,例如利用Volatile关键字,使用重入锁实现线程同步和ThreadLocal类。
加上锁后的效果:
在这里插入图片描述
这样就可以看出线程没有了冲突而且还交替进行。

线程的生命周期(状态)

在这里插入图片描述
1.新建状态
2.就绪状态
3.运行状态
4.阻塞状态
5.死亡状态

线程的注意事项

1.启动线程不是用run方法,而是用start方法。
2.执行线程的时候先执行完main函数中的主线程然后再执行子线程。
3.实现Runable接口后不能直接用start方法还是需要new一个Thread类然后调用start方法启动线程。
4.结束线程的时候最好不要用stop()方法,因为stop方法已经过时了,然后会破坏原子的逻辑性,可以用wait()和sleep()方法。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值