首先我们来了解一下概念
进程:是一个正在执行的程序,每一个进程执行都有一个顺序,该顺序是一个执行路径,或者叫一个控制单元。
线程:就是进程中的一个独立的控制单元,线程在控制着进程的执行。
一个进程中至少有一个线程。
Java VM 启动的时候会有一个进程java.exe
该进程中至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中,该线程称之为主线程。
另:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。
多线程存在的意义:使用线程可以把占据时间长的程序中的任务放到后台去处理;用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度;程序的运行速度可能加快;在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了,在这种情况下可以释放一些珍贵的资源如内存占用等等。
线程的创建方式:
通过对API的查找,java已经提供了对线程这类事务的描述,就是Thread类,
创建线程的第一种方式,继承Thread类
步骤:
1.定义类继承Thread类
2.复写Thread类中的run方法,目的:把自定义要运行多线程的代码写入run方法中
3.调用线程的start方法,该方法的作用:启动线程,调用run方法
为什么要复写run方法?
Thread类用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法,也就是说,Thread类中的run方法,用于存储线程要运行的代码
发现每次运行结果都不同,因为多个线程都获取cpu的执行权,cpu执行到谁,谁就运行。
明确一点,在某一时刻,只能有一个程序在运行,多核除外。
cpu在做着快速切换,以达到看上去同时运行的效果。
我们可以形象的把多线程的运行行为看成是互相抢夺cpu的执行权
package first;
public class ThreadTest {
public static void main(String[] args) {
ThreadDemo thread=new ThreadDemo();//创建好一个线程
thread.start();
//thread.run()//这样也可以运行,但没有多线程的效果,是先后运行的了
for(int i=0;i<10;i++){
System.out.println("main Run---->"+i);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class ThreadDemo extends Thread{
public void run() {//复写run方法
for(int i=0;i<10;i++){
System.out.println("Thread Run*****"+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程的五种状态图:
冻结状态:又分为睡眠和等待两种状态。
临时状态:调用了start方法后,还在等待cpu来处理启动
冻结状态和临时状态的区别是,是否有执行权。
创建线程的第二种方式:
需求:简单的卖票程序,实现多个窗口同时卖票
1.定义类,实现Runnable借口
2.覆盖Runnable接口中的run方法
:将线程要运行的代码存放在run方法中
3.通过Thread类建立线程对象
4.将Runnable借口的子类对象作为实际参数传递给Thread的构造函数
:为什么要将Runnable借口的子类对象传递给Thread的构造函数?
因为自定义的run方法所属的对象是Runnable借口的子类对象,
所以要让线程去运行指定对象的run方法,就必须明确该run方法所属对象
5.调用Thread类的start方法开启线程并调用Runnable借口子类的run方法
package first;
class Ticket implements Runnable{ //extends Thread{
//如果是静态的话,所有的线程会共享这100张票
/*private static int ticket =100;*/
//如果不是静态的话,每一个线程对象都会创建这个ticket对象,也即每个线程拥有100张票卖。
//这时候,如果还是采用继承Thread类的方法就不行了,需要使用实现Runnable接口创建线程
private int ticket =1000;
//定义一个对象,为同步使用,任意
Object obj= new Object();
public void run() {
//在这里声明的对象是无效的
/*Object obj= new Object(); */
while(true){
synchronized (obj) {
if(ticket>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+".....sale : "+ ticket--);
}
}
}
}
}
public class TicketDemo {
public static void main(String[] args) {
Ticket t = new Ticket();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
实现 方式和继承方式的区别:
实现方式的好处:避免了继承方式的单继承的局限性
在定义线程时,建议使用实现方式
继承Thread的线程代码存放在Thread子类的run方法中
实现Runnable线程代码存放在借口的子类run方法中
下面有一个需求:
银行有一个金库,有两个储户分别存300元,每次存一百,存3次
package first;
/*
* 1.要明确哪些代码是多线程运行代码
* 2.哪些数据是共享数据
* 3.明确多线程运行代码中哪些语句是操作共享数据的
*/
public class BankDemo {
public static void main(String[] args) {
Cus cus1=new Cus();
Cus cus2=new Cus();
Thread t1=new Thread(cus1);
Thread t2=new Thread(cus2);
t1.start();
t2.start();
}
}
class Bank{
private int sum;
public synchronized void add(int n,String name){//同步函数
sum+=n;
System.out.println(name+" sum="+sum);
}
}
class Cus implements Runnable{
Bank b=new Bank();
@Override
public void run() {
for(int i=0;i<3;i++)
b.add(100,Thread.currentThread().getName());
}
}
单例设计模式
//饿汉式
class Single{
private static final Single s=new Single();
private Single(){}
public static Single getInstance(){return s;}
}
//懒汉式
//实例的延迟加载,但在多线程时会出错,要加锁
class Single{
private static Single s=null;
private Single(){}
private static Single getInstance(){
if(s==null){
synchronized(Single.class){
if(s==null){
s=new Single();
}
}
}
return s;
}
}
下面来一个简单的死锁程序作为结束:
死锁:简单的讲就是a需要b的资源,同时b也需要a的资源,然后两个进程就在等待,发生了死锁
package first;
/*
* 死锁
*/
public class DeadLockDemo {
public static void main(String[] args) {
Thread t1=new Thread(new TestDeadLock(true));
Thread t2=new Thread(new TestDeadLock(false));
t1.start();
t2.start();
}
}
class TestDeadLock implements Runnable{
private boolean flag;
public TestDeadLock(boolean flag) {
this.flag=flag;
}
@Override
public void run() {
if (flag) {
synchronized (MyLock.locka) {
System.out.println("if locka");
synchronized (MyLock.lockb) {
System.out.println("if lockb");
}
}
}else{
synchronized (MyLock.lockb) {
System.out.println("else lockb");
synchronized (MyLock.locka) {
System.out.println("else locka");
}
}
}
}
}
class MyLock{
static Object locka=new Object();
static Object lockb=new Object();
}
谢谢!