java中多线程的学习

1.什么是进程?

​ 应用程序的一个运行实例 包含程序所需要的资源的内存区域,是操作系统进行资源分配的单元

进程隔离了正在执行的不同程序

优点:进程间相互独立互补影响

2.什么是线程?

​ 进程中的一个执行单元(进程是程序的边界,要靠线程执行程序)线程执行方法 执行完毕释放线程是CPU分配时间片的单位 一个进程包含多个线程

且线程相互独立 共享当前进程的资源

3.操作系统的分类?

​ 单任务和多任务

1. 单任务操作系统:


在这里插入图片描述

2.多任务操作系统:

1.单核CPU多任务操作系统:

在这里插入图片描述

​ 2.

4.如何创建一个线程?

​ 第一种方式:创建Thread子类

​ java.lang.Thread 描述线程的类 我们想实现多线程 必须继承 Thread类

1.实现步骤:

​ 1.创建一个Thread子类

​ 2.重写run方法布置任务

​ 3.创建Thread子类对象

​ 4.调用Thread类中的Start方法 开启新线程 执行run方法

2.案例:

package MapList;

public class Thread1 extends Thread {
//2.重写Thread类中的run方法 设置线程任务
public void run() {
for(int i=0;i<20;i++) {
System.out.println(“run:”+i);
}
}

}

package MapList;

public class MyThread {
public static void main(String[]args) {
Thread1 th=new Thread1();
th.start();
for(int i=0;i<20;i++) {
System.out.println(“main”+i);
}

}

}
结果:
main0
run:0
main1
main2
main3
main4
main5
run:1
main6
run:2
main7
run:3
main8
run:4
main9
main10
run:5
run:6
run:7
run:8
run:9
run:10
run:11
run:12
run:13
run:14
run:15
run:16
run:17
main11
main12
main13
main14
main15
main16
main17
main18
main19
run:18
run:19

第二种方式:实现runnable接口

java. lang.Runable 接口应该由那些打算通过某一线程执行其实例的类实现

类必须定义一个 无参数的方法(方法用来布置任务)

Thread 类方法和构造方法

Thread(Runnabe target) 分配新的Thread对象

Thread(Runnable Target,String name)分配新的Thread对象

1.实现步骤:

1.创建一个Runnable接口实现类

2.在实现类中 重写Runnable接口的run方法

3.创建Runnable的实现类对象

4.创建Thread对象 构造方法中传递Runnable实现类对象

5.调用Thread的start方法

2.Runnable实现多线程的好处:

1.避免了单继承的局限性

2.增强了程序的拓展性,降低了耦合度(解耦)把继承关系变成组合关系

3.案例:

package MapList;

public class RunnableImpl implements Runnable{

	@Override
	public void run() {
		// TODO 自动生成的方法存根
		for(int i=0;i<20;i++) {
			System.out.println("run:"+i);
		}
	}
	public static void main(String[]args) {
		Runnable r=new RunnableImpl();
		Thread td=new Thread(r);
		td.start();
		
	}

}
package MapList;

public class MyThread {
	public static void main01(String[]args) {
	    Thread1 th=new Thread1();//继承
	    th.start();
		run();
        
	}

	private static void run() {
		for(int i=0;i<20;i++) {
			System.out.println("main"+i);
		}
	}
	public static void main(String[]args) {
		Runnable r=new RunnableImpl();
		
		Thread td=new Thread(r); // 组合   任务与线程
		td.start();
		run();
		
	}

}
结果:
main0
run:0
main1
main2
main3
main4
main5
run:1
main6
run:2
main7
run:3
main8
run:4
main9
main10
run:5
run:6
run:7
run:8
run:9
run:10
run:11
run:12
run:13
run:14
run:15
run:16
run:17
main11
main12
main13
main14
main15
main16
main17
main18
main19
run:18
run:19

4.匿名内部类实现多线程:

            ```
public static void main(String[]args) {
	Runnable runnable=new Runnable() {

		@Override
		public void run() {
			// TODO 自动生成的方法存根
			for(int i=0;i<20;i++) {
				System.out.println("runnable:"+i);
		}
		
	}
};
new Thread(runnable).start();
new Thread(new Runnable() {//匿名内部类和匿名对象一块使用
		public void run() {
			for(int i=0;i<20;i++) {
				System.out.println("第三"+i);
			}
		}
	}).start();
Thread td=	new Thread() {
		public void run() {
			for(int i=0;i<20;i++) {
				System.out.println("run:"+i);
			}
		}
	};
	td.start();
	run();

}

}
结果:
runnable:0
runnable:1
runnable:2
runnable:3
runnable:4
runnable:5
runnable:6
runnable:7
runnable:8
runnable:9
runnable:10
runnable:11
runnable:12
runnable:13
runnable:14
runnable:15
runnable:16
runnable:17
runnable:18
main0
main1
main2
main3
run:0
runnable:19
run:1
main4
main5
run:2
run:3
run:4
run:5
run:6
run:7
run:8
run:9
run:10
run:11
run:12
main6
run:13
run:14
run:15
run:16
run:17
run:18
run:19
第三0
main7
main8
第三1
第三2
第三3
第三4
第三5
main9
第三6
main10
main11
第三7
main12
第三8
main13
第三9
main14
第三10
main15
第三11
第三12
第三13
第三14
main16
第三15
main17
第三16
main18
main19
第三17
第三18
第三19

            ```

5.Java如何决定执行那个线程

​ java是抢占式执行 可以设置线程的优先级(执行概率会大大提高)

6.多线程实现的原理

1.主线程执行原理

public class Demo1{

​ public static void main(String[]args){

​ System.out.println(“HelloWorld”)

​ }

​ }

​ 分析:JVM执行main方法 main方法会进入栈内存,jvm会找操作系统开辟一条main方法通向cpu的执行路径,cup就可以通过这个执行路径来执行main方法,而这个路径取一个名字叫main(主)线程


在这里插入图片描述

2.多线程执行原理

在这里插入图片描述

3.内存上多线程实现的原理


在这里插入图片描述

7.线程冲突

1.线程中常用的方法

​ setName getName sleep currentThread

2.setName和getName案例
                            ```
         package MapList;

public class Thread1 extends Thread {

//2.重写Thread类中的run方法  设置线程任务
public void run() {
	setName("线程1");
	for(int i=0;i<20;i++) {
		System.out.println(getName()+i);
	}
}

}
public static void main(String[]args) {
Thread1 td=new Thread1();
//td.setName(“线程1”);
td.start();
String name= td.getName();

	System.out.println(name);
}

}
结果:
Thread-0
线程10
线程11
线程12
线程13
线程14
线程15
线程16
线程17
线程18
线程19
线程110
线程111
线程112
线程113
线程114
线程115
线程116
线程117
线程118
线程119

2.sleep方法的案例

public static void main(String[]args) throws InterruptedException {
// Thread1 td=new Thread1();
// td.setName(“线程1”);
// td.start();
// String name= td.getName();
//
// System.out.println(name);
for(int i=0;i<20;i++) {

		Thread.sleep(1000);//睡眠毫秒
		System.out.println(i);
	}
}

}
结果:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

3.currentThread方法的案例

public static void main(String[]args) throws InterruptedException {
// Thread1 td=new Thread1();
// td.setName(“线程1”);
// td.start();
// String name= td.getName();
//
// System.out.println(name);
for(int i=0;i<20;i++) {
//Thread.sleep(1000);
System.out.println(i);
}
System.out.println(Thread.currentThread());
结果:
Thread[main,5,main]
System.out.println(Thread.currentThread().getName());
结果:
main
System.out.println(Thread.currentThread().currentThread().currentThread());
//链式编程
结果:
Thread[main,5,main]

}

}
结果:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

                       ```

4.线程冲突中买票的案例:

                                       ```

package MapList;

public class RunnableImpl1 implements Runnable{
//总票数
private int ticket=100;
//设置线程任务买票
public void run() {
while(true){
//使用无线循环让买票操作重复执行
if(ticket>0) {
try {
Thread.sleep(10);//模拟出票的过程

			}catch(Exception e) {
				
			}
			System.out.println(Thread.currentThread().getName()+"正在买---->"+ticket+"张票");
			ticket--;
			
		}
		
	}
}

}
public static void main(String[]args) {
Runnable r=new RunnableImpl1();
Thread td=new Thread®;
td.start();
Thread td1=new Thread®;
td1.start();

}

}
结果:
Thread-1正在买---->100张票
Thread-0正在买---->100张票
Thread-0正在买---->98张票
Thread-1正在买---->98张票
Thread-1正在买---->96张票
Thread-0正在买---->96张票
Thread-1正在买---->94张票
Thread-0正在买---->94张票
Thread-0正在买---->92张票
Thread-1正在买---->92张票
Thread-1正在买---->90张票
Thread-0正在买---->90张票
Thread-0正在买---->88张票
Thread-1正在买---->88张票
Thread-0正在买---->86张票
Thread-1正在买---->86张票
Thread-0正在买---->84张票
Thread-1正在买---->84张票
Thread-0正在买---->82张票
Thread-1正在买---->82张票
Thread-0正在买---->80张票
Thread-1正在买---->80张票
Thread-0正在买---->78张票
Thread-1正在买---->78张票
Thread-1正在买---->76张票
Thread-0正在买---->76张票
Thread-0正在买---->74张票
Thread-1正在买---->74张票
Thread-1正在买---->72张票
Thread-0正在买---->72张票
Thread-1正在买---->70张票
Thread-0正在买---->70张票
Thread-1正在买---->68张票
Thread-0正在买---->68张票
Thread-0正在买---->66张票
Thread-1正在买---->66张票
Thread-1正在买---->64张票
Thread-0正在买---->64张票
Thread-0正在买---->62张票
Thread-1正在买---->62张票
Thread-1正在买---->60张票
Thread-0正在买---->60张票
Thread-0正在买---->58张票
Thread-1正在买---->58张票
Thread-0正在买---->56张票
Thread-1正在买---->56张票
Thread-0正在买---->54张票
Thread-1正在买---->54张票
Thread-1正在买---->52张票
Thread-0正在买---->52张票
Thread-0正在买---->50张票
Thread-1正在买---->50张票
Thread-0正在买---->48张票
Thread-1正在买---->48张票
Thread-0正在买---->46张票
Thread-1正在买---->46张票
Thread-1正在买---->44张票
Thread-0正在买---->44张票
Thread-0正在买---->42张票
Thread-1正在买---->42张票
Thread-0正在买---->40张票
Thread-1正在买---->40张票
Thread-0正在买---->38张票
Thread-1正在买---->38张票
Thread-1正在买---->36张票
Thread-0正在买---->36张票
Thread-1正在买---->34张票
Thread-0正在买---->34张票
Thread-1正在买---->32张票
Thread-0正在买---->32张票
Thread-1正在买---->30张票
Thread-0正在买---->30张票
Thread-0正在买---->28张票
Thread-1正在买---->28张票
Thread-1正在买---->26张票
Thread-0正在买---->26张票
Thread-1正在买---->24张票
Thread-0正在买---->24张票
Thread-1正在买---->22张票
Thread-0正在买---->22张票
Thread-1正在买---->20张票
Thread-0正在买---->20张票
Thread-1正在买---->18张票
Thread-0正在买---->18张票
Thread-1正在买---->16张票
Thread-0正在买---->16张票
Thread-0正在买---->14张票
Thread-1正在买---->14张票
Thread-0正在买---->12张票
Thread-1正在买---->12张票
Thread-0正在买---->10张票
Thread-1正在买---->10张票
Thread-0正在买---->8张票
Thread-1正在买---->8张票
Thread-0正在买---->6张票
Thread-1正在买---->6张票
Thread-0正在买---->4张票
Thread-1正在买---->4张票
Thread-0正在买---->2张票
Thread-1正在买---->2张票
Thread-0正在买---->0张票
注意:
两个人同时去买票线程不安全
t0进来了线程抢到了cup的执行权 进入到run方法 执行到if之后 就失去了cpu执行权( 睡了) t1也进来了 (睡了)出现了一样的数据在减减之前同时执行到System.out.println()了。 (线程不安全)

                                       ```

2.案例2 :
public static void main(String[]args) {
		Runnable r=new RunnableImpl1();
		  Thread td=new Thread(r);
		  td.start();
		  Thread td1=new Thread(r);
		  td1.start();
		  Thread td2=new Thread(r);
		  td1.start();
}
}




package MapList;

public class RunnableImpl1 implements Runnable{
	//总票数
	private int ticket=100;
	//设置线程任务买票
	public void run() {
		while(true){
			//使用无线循环让买票操作重复执行
			if(ticket>0) {
				try {
					Thread.sleep(10);//模拟出票的过程
					
				}catch(Exception e) {
					
				}
				System.out.println(Thread.currentThread().getName()+"正在买---->"+ticket+"张票");
				ticket--;
				
			}
			
		}
	}

}
结果:
Thread-0正在买---->100张票
Thread-0正在买---->99张票
Thread-0正在买---->98张票
Thread-1正在买---->97张票
Thread-0正在买---->96张票
Thread-0正在买---->95张票
Thread-1正在买---->94张票
Thread-0正在买---->93张票
Thread-1正在买---->92张票
Thread-0正在买---->91张票
Thread-0正在买---->90张票
Thread-1正在买---->89张票
Thread-0正在买---->88张票
Thread-0正在买---->87张票
Thread-1正在买---->86张票
Thread-0正在买---->85张票
Thread-0正在买---->84张票
Thread-1正在买---->83张票
Thread-0正在买---->82张票
Thread-0正在买---->81张票
Thread-1正在买---->80张票
Thread-0正在买---->79张票
Thread-1正在买---->78张票
Thread-0正在买---->77张票
Thread-1正在买---->76张票
Thread-0正在买---->75张票
Thread-1正在买---->74张票
Thread-0正在买---->73张票
Thread-0正在买---->72张票
Thread-1正在买---->71张票
Thread-0正在买---->70张票
Thread-1正在买---->69张票
Thread-0正在买---->68张票
Thread-0正在买---->67张票
Thread-1正在买---->66张票
Thread-0正在买---->65张票
Thread-0正在买---->64张票
Thread-1正在买---->63张票
Thread-0正在买---->62张票
Thread-1正在买---->61张票
Thread-0正在买---->60张票
Thread-0正在买---->59张票
Thread-1正在买---->58张票
Thread-0正在买---->57张票
Thread-0正在买---->56张票
Thread-1正在买---->55张票
Thread-0正在买---->54张票
Thread-0正在买---->53张票
Thread-1正在买---->52张票
Thread-0正在买---->51张票
Thread-1正在买---->50张票
Thread-0正在买---->49张票
Thread-0正在买---->48张票
Thread-1正在买---->47张票
Thread-0正在买---->46张票
Thread-1正在买---->45张票
Thread-0正在买---->44张票
Thread-1正在买---->43张票
Thread-0正在买---->42张票
Thread-0正在买---->41张票
Thread-1正在买---->40张票
Thread-0正在买---->39张票
Thread-1正在买---->38张票
Thread-0正在买---->37张票
Thread-0正在买---->36张票
Thread-1正在买---->35张票
Thread-0正在买---->34张票
Thread-0正在买---->33张票
Thread-1正在买---->32张票
Thread-0正在买---->31张票
Thread-0正在买---->30张票
Thread-1正在买---->29张票
Thread-0正在买---->28张票
Thread-1正在买---->27张票
Thread-1正在买---->26张票
Thread-0正在买---->25张票
Thread-1正在买---->24张票
Thread-0正在买---->23张票
Thread-1正在买---->22张票
Thread-0正在买---->21张票
Thread-1正在买---->20张票
Thread-0正在买---->19张票
Thread-0正在买---->18张票
Thread-1正在买---->17张票
Thread-0正在买---->16张票
Thread-1正在买---->15张票
Thread-1正在买---->14张票
Thread-0正在买---->13张票
Thread-0正在买---->12张票
Thread-1正在买---->11张票
Thread-0正在买---->10张票
Thread-0正在买---->9张票
Thread-1正在买---->8张票
Thread-0正在买---->7张票

8.如何解决线程安全的问题

1.第一种方式 同步代码块

​ Synchronized(锁对象){

​ 可能会出现线程安全的问题的代码

​ }

1.案例:

package MapList;

public class RunnableImpl1 implements Runnable{
//总票数
private int ticket=100;
Object obj=new Object();
//设置线程任务买票
public void run() {
while(true){
//使用无线循环让买票操作重复执行
//锁对象 任意
synchronized(obj) {
if(ticket>0) {
try {
Thread.sleep(10);//模拟出票的过程

				}catch(Exception e) {
					
				}
				System.out.println(Thread.currentThread().getName()+"正在买---->"+ticket+"张票");
				ticket--;
				
			
		}
		
			
		}
		
	}
}

}

public static void main(String[]args) {
Runnable r=new RunnableImpl1();
Thread td=new Thread®;
td.start();
Thread td1=new Thread®;
td1.start();
Thread td2=new Thread®;
td1.start();

}

}

结果:
Thread-0正在买---->100张票
Thread-0正在买---->99张票
Thread-0正在买---->98张票
Thread-0正在买---->97张票
Thread-0正在买---->96张票
Thread-0正在买---->95张票
Thread-1正在买---->94张票
Thread-1正在买---->93张票
Thread-1正在买---->92张票
Thread-1正在买---->91张票
Thread-1正在买---->90张票
Thread-1正在买---->89张票
Thread-1正在买---->88张票
Thread-1正在买---->87张票
Thread-1正在买---->86张票
Thread-1正在买---->85张票
Thread-1正在买---->84张票
Thread-1正在买---->83张票
Thread-1正在买---->82张票
Thread-1正在买---->81张票
Thread-1正在买---->80张票
Thread-1正在买---->79张票
Thread-1正在买---->78张票
Thread-1正在买---->77张票
Thread-1正在买---->76张票
Thread-1正在买---->75张票
Thread-1正在买---->74张票
Thread-1正在买---->73张票
Thread-1正在买---->72张票
Thread-1正在买---->71张票
Thread-1正在买---->70张票
Thread-1正在买---->69张票
Thread-1正在买---->68张票
Thread-1正在买---->67张票
Thread-1正在买---->66张票
Thread-1正在买---->65张票
Thread-1正在买---->64张票
Thread-1正在买---->63张票
Thread-1正在买---->62张票
Thread-1正在买---->61张票
Thread-1正在买---->60张票
Thread-1正在买---->59张票
Thread-1正在买---->58张票
Thread-1正在买---->57张票
Thread-1正在买---->56张票
Thread-1正在买---->55张票
Thread-1正在买---->54张票
Thread-1正在买---->53张票
Thread-1正在买---->52张票
Thread-1正在买---->51张票
Thread-1正在买---->50张票
Thread-1正在买---->49张票
Thread-1正在买---->48张票
Thread-1正在买---->47张票
Thread-1正在买---->46张票
Thread-1正在买---->45张票
Thread-1正在买---->44张票
Thread-1正在买---->43张票
Thread-1正在买---->42张票
Thread-1正在买---->41张票
Thread-1正在买---->40张票
Thread-1正在买---->39张票
Thread-1正在买---->38张票
Thread-1正在买---->37张票
Thread-1正在买---->36张票
Thread-1正在买---->35张票
Thread-1正在买---->34张票
Thread-1正在买---->33张票
Thread-1正在买---->32张票
Thread-1正在买---->31张票
Thread-1正在买---->30张票
Thread-1正在买---->29张票
Thread-1正在买---->28张票
Thread-1正在买---->27张票
Thread-1正在买---->26张票
Thread-1正在买---->25张票
Thread-1正在买---->24张票
Thread-1正在买---->23张票
Thread-1正在买---->22张票
Thread-1正在买---->21张票
Thread-1正在买---->20张票
Thread-1正在买---->19张票
Thread-1正在买---->18张票
Thread-1正在买---->17张票
Thread-1正在买---->16张票
Thread-1正在买---->15张票
Thread-1正在买---->14张票
Thread-1正在买---->13张票
Thread-1正在买---->12张票
Thread-1正在买---->11张票
Thread-1正在买---->10张票
Thread-1正在买---->9张票
Thread-1正在买---->8张票
Thread-1正在买---->7张票
Thread-1正在买---->6张票
Thread-1正在买---->5张票
Thread-1正在买---->4张票
Thread-1正在买---->3张票
Thread-1正在买---->2张票
Thread-1正在买---->1张票

                                       ```

注意事项:

​ 1.通过代码块中的锁对象 可以使用任意的对象

​ 2.但是必须保证多个线程使用的锁对象是一个

​ 3.锁对象的作用:

​ 把同步代码块锁住 只让一个线程在同步代码块执行

2.第二种 使用同步方法

步骤:1.把访问了共享数据的代码抽取出来放到一个方法中

​ 2.把方法添加关键字synchronized

案例1:

package MapList;

public class RunnableImpl1 implements Runnable{
//总票数
private int ticket=10;
Object obj=new Object();
//设置线程任务买票
public void run() {
while(true){
//使用无线循环让买票操作重复执行
//锁对象 任意
//synchronized(obj) {
extracted();

		}
		
			
		//}
		
	}
	//锁的是this
 private synchronized void extracted() {
      synchronized(this){
           	 if(ticket>0) {
			try {
				Thread.sleep(10);//模拟出票的过程
				
			}catch(Exception e) {
				
			}
			System.out.println(Thread.currentThread().getName()+"正在买---->"+ticket+"张票");
			ticket--;
      }

			
 }
}

}

public static void main(String[]args) {
	Runnable r=new RunnableImpl1();
	  Thread td=new Thread(r);
	  td.start();
	  Thread td1=new Thread(r);
	  td1.start();
	  Thread td2=new Thread(r);
	  td1.start();
	  
	  
	  
}

}

3.静态的同步方法

1.锁对象的问题:

​ this是创建对象之后产生的 静态方法属于类优先于this所以静态没有this

2.静态方法的锁对象是本类class属性----->class文件对象(反射)

案例:

package MapList;

public class RunnableImpl1 implements Runnable{
//总票数
private static int ticket=10;
Object obj=new Object();
//设置线程任务买票
public void run() {
while(true){
//使用无线循环让买票操作重复执行
//锁对象 任意
//synchronized(obj) {
extracted1();

		}
		
			
		//}
		
	}
 private static synchronized void extracted1() {
     synchronized(RunnableImpl1.class){
      if(ticket>0) {
			try {
				Thread.sleep(10);//模拟出票的过程
				
			}catch(Exception e) {
				
			}
			System.out.println(Thread.currentThread().getName()+"正在买---->"+ticket+"张票");
			ticket--;
			
     
     }
	
 }
}

}

public static void main(String[]args) {
	Runnable r=new RunnableImpl1();
	  Thread td=new Thread(r);
	  td.start();
	  Thread td1=new Thread(r);
	  td1.start();
	  Thread td2=new Thread(r);
	  td1.start();
	  
	  
	  
}

}

                                  this是创建对象之后产生的   静态方法属于类优先于this所以静态没有this

2.静态方法的锁对象是本类class属性----->class文件对象(反射)

案例:

package MapList;

public class RunnableImpl1 implements Runnable{
//总票数
private static int ticket=10;
Object obj=new Object();
//设置线程任务买票
public void run() {
while(true){
//使用无线循环让买票操作重复执行
//锁对象 任意
//synchronized(obj) {
extracted1();

		}
		
			
		//}
		
	}
 private static synchronized void extracted1() {
     synchronized(RunnableImpl1.class){
      if(ticket>0) {
			try {
				Thread.sleep(10);//模拟出票的过程
				
			}catch(Exception e) {
				
			}
			System.out.println(Thread.currentThread().getName()+"正在买---->"+ticket+"张票");
			ticket--;
			
     
     }
	
 }
}

}

public static void main(String[]args) {
	Runnable r=new RunnableImpl1();
	  Thread td=new Thread(r);
	  td.start();
	  Thread td1=new Thread(r);
	  td1.start();
	  Thread td2=new Thread(r);
	  td1.start();
	  
	  
	  
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值