`
bing2012
  • 浏览: 11199 次
  • 性别: Icon_minigender_1
  • 来自: 山东潍坊
最近访客 更多访客>>
社区版块
存档分类
最新评论

多线程学习笔记

 
阅读更多
进程是一个正在执行的程序
   每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。
   Java VM 启动的时候会有一个进程java.exe
   一个进程中至少有一个线程负责Java程序的运行,而且这个线程运行的代码存放在main方法中,该线程称之为主线程
扩展:其实更细节说明虚拟机,虚拟机不止启动一个线程,还有负责垃圾回收的线程。
 
 
  第一种创建线程的步骤:
  1.创建类继承Thread类或者实现Runable接口
  2.复写Run方法
  3.调用线程的start方法
      该方法有两个作用:启动线程 ,调用run方法
示例如下:假设有4个售票窗口同时进行售票,每一个售票窗口可以理解为一个线程,四个窗口同时售票
也就是四个线程同时启动,而假定票数是10张,这样....每个窗口也就是线程都在运行时产生四个对象,会
有40张票,即每个对象产生10张票,一个线程,总共40张票4个线程,为了解决这个问题,可以考虑将
Ticket类中的num设置为static使四个对象共享这10张票。
Ticket类中的num设置为static使四个对象共享这10张票。
//Ticke类示例代码如下:
public class Ticket extends Thread{//实现线程需继承Thread类
	private static int ticket_num=10;//静态共享数据假定为10张票
	@Override
	public void run() {//复写run方法
		while(ticket_num>0)
		{
			if(ticket_num>0)
			{
				System.out.println(Thread.currentThread().getName()+"售票"+--ticket_num);
				//Thread为类名,currentThread()为静态方法,可以由类名调用,作用是返回当前线程对象,getName(),拿到当前线程的名字
			}			
		}
	}
}
//TestMain示例代码如下:
public class TestMain {
	public static void main(String[] args) {
		Ticket t1=new Ticket();//创建四个Thread类的子对象
		Ticket t2=new Ticket();
		Ticket t3=new Ticket();
		Ticket t4=new Ticket();
		t1.start();t2.start();t3.start();t4.start();//启动这四个对象的线程
	}
}

输出如下:Thread-1售票9
Thread-1售票6
Thread-1售票5
Thread-1售票4
Thread-1售票3
Thread-1售票2
Thread-1售票1
Thread-1售票0
Thread-0售票7
Thread-3售票8
--------------------------------可以观察到四个线程共享tiket_num这个数据,但是静态的对象属性生命周期过长,而且需要建立四个对象 所以可以考虑用实现Runnable接口的
方式来实现。
     
     
为什么要覆盖Run方法?
Thread类用于描写线程
该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法
也就是说Thread类中的Run方法是用于存储线程要运行的代码

star方法和run方法的区别:
start--开启线程并执行该线程的run方法
run--仅仅是对象调用方法。而线程创建了,并没有执行  也就是只执行run方法内的代码 但是没有多线程


static Thread currentThread();获取当前线程对象
getName();获取线程名称
设置线程名称:setName或者构造函数
注意:每一个变量在线程当中都有独立的一份


创建线程的第二种方式:实现Runnable接口
步骤:
1.定义类实现Runable接口
2.覆盖Runable接口中的run方法
将线程要运行的代码放在该run方法中
3.通过Thread类建立线程对象
4.将Runable接口的子类对象作为实际参数传递给Thread类构造函数
为什么要将Runnable接口的子类对象传递给Thread的构造函数
因为,自定义的run方法所属的对象是实现Runnable接口的子类对象
所以要让线程去执行指定对象的run方法。就必须明确该run方法所属的对象
5.调用Thread类的start方法开启线程并调用Runable接口子类的run方法

售票示例如下:
public class Ticket implements Runnable{
	private String name;//售票窗口名字
	private int num;//票数
	Ticket(String name,int num)
	{
		this.name=name;this.num=num;
	}
	public void run() {//复写run方法
		while(this.num>0)
		{
			System.out.println(Thread.currentThread().getName()+"售票"+this.num--);
		}
	}
}
//TestMain程序代码如下:
public class TestMain {
	public static void main(String[] args) {
		Ticket t1=new Ticket("售票窗口",10);//创造实现Runnable接口的子类对象
		new Thread(t1).start();//开启3个线程
		new Thread(t1).start();
		new Thread(t1).start();
	}
}


输出如下:Thread-0售票10
Thread-2售票8
Thread-1售票9
Thread-1售票5
Thread-1售票4
Thread-1售票3
Thread-1售票2
Thread-1售票1
Thread-0售票6
Thread-2售票7



实现方式和继承方式有什么区别?
实现方式的好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。
继承Thread:线程代码存放在Thread子类run方法中。
实现Runnable,线程代码存放在接口子类的run方法中。

多线程的安全隐患:(需要多加注意)
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没
有执行完,另一个线程参与进来执行。导致了共享数据的错误。
解决办法:对于多条操作共享数据的语句,只能让一个线程都执行完,其他的线程才能
参与执行。
Java对于多线程的安全问题提供了专业的解决方案,就是同步代码块。
synchronized(对象){
需要被同步的代码
}

如何找到问题 找到该同步哪些代码块?
1.明确哪些代码是需要多线程运行代码。
2.明确共享数据。
3.明确多线程运行代码中的哪些语句是操作共享数据的。


同步函数---同步函数用的是哪一个锁?
---同步函数用的锁就是this,函数需要被对象调用,那么函数都有一个所属的对象的引用。就是this.
所以同步函数使用的锁是this.
验证示例:通过以下的程序来验证。需求为 --通过两个线程来买票一个线程在同步代码块中,另一
个线程在同步函数中。都在执行买票动作。
代码如下:
/**
 * 售票类 有两个线程 同步代码块和同步函数 注意同步函数的锁为this而同步代码块的锁要达到
 * 安全的目的则必须与同步函数的锁相同 也就是this
 * @author bing
 *
 */
public class Ticket implements Runnable{
	private static int tickt=10;
	Object obj = new Object();
	boolean flag=true;
	public void run()//同步代码块
	{	
		if(flag)
		{
			while(true)
			{
				//synchronized (obj)//注意这里的锁是obj,这样与同步函数用的不是一个锁,所以会产生数据异常,比如售票时卖到0号票..
				//synchronized (this)//这里用this锁,与同步函数用同一个锁
				{
					if(tickt>0)
					{
						try{Thread.sleep(10);}catch(Exception e){}
						System.out.println("同步代码块进程---"+Thread.currentThread().getName()
								+"-----sale:"+tickt--);
					}
				}
				
			}
		}else
			{
				while(true)
				{
					show();
				}
			}		
	}
	public static synchronized void show()//同步函数
	{
		if(tickt>0)
		{
			try{Thread.sleep(10);}catch(Exception e){}
			System.out.println("同步函数进程---"+Thread.currentThread().getName()
					+"-----sale:"+tickt--);
		}
	}
}
//测试程序代码如下:
/**
 * 验证线程锁,同步代码块和同步函数的控制通过flag旗帜来控制
 * 注意主线程需要sleep一段时间 
 * @author bing
 *
 */
public class TestMain {
	public static void main(String[] args) throws InterruptedException {
		Ticket aTicket=new Ticket();
		Thread t1=new Thread(aTicket);
		Thread t2=new Thread(aTicket);
		t1.start();//线程t1开始启动,启动的时间短,非常有可能被main主线程抢走执行权,所以让主线程休息一会
		Thread.currentThread().sleep(10);
		aTicket.flag=false;System.out.println("-------------------------------------");
		t2.start();
	}
}

输出结果如下:
-------------------------------------
同步代码块进程---Thread-0-----sale:10
同步函数进程---Thread-1-----sale:8
同步代码块进程---Thread-0-----sale:9
同步代码块进程---Thread-0-----sale:7
同步函数进程---Thread-1-----sale:7
同步函数进程---Thread-1-----sale:6
同步代码块进程---Thread-0-----sale:5
同步代码块进程---Thread-0-----sale:4
同步函数进程---Thread-1-----sale:3
同步函数进程---Thread-1-----sale:2
同步代码块进程---Thread-0-----sale:1------------可以观察输出有序且线程Thread1和Thread0交替执行

那么上面的例子验证了同步函数的锁是this  那么静态同步函数的锁是什么呢?
--首先不是this,因为在static 中没有this.静态进内存是,内存中没有本类对象,但是一定有该类对应
的字节码文件对象。--->也就是类名.class  该对象类型是Class 即在静态函数中同步锁为类名.class

示例代码如下:
package DemoSynchronized_Static;
/**
 * 售票类 有两个线程 同步代码块和同步函数 注意同步函数的锁为this而同步代码块的锁要达到
 * 安全的目的则必须与同步函数的锁相同 也就是this
 * @author bing
 *
 */
public class Ticket implements Runnable{
	private static int tickt=10;
	Object obj = new Object();
	boolean flag=true;
	public void run()//同步代码块
	{	
		if(flag)
		{
			while(true)
			{
				//synchronized (obj)//注意这里的锁是obj,这样与同步函数用的不是一个锁,所以会产生数据异常,比如售票时卖到0号票..
				synchronized (Ticket.class)//这里用的是所在类的字节码文件对象,即类名.calss
				{
					if(tickt>0)
					{
						try{Thread.sleep(100);}catch(Exception e){}
						System.out.println("同步代码块进程---"+Thread.currentThread().getName()
								+"-----sale:"+tickt--);
					}
				}
				
			}
		}else
			{
				while(true)
				{
					show();//调用同步函数
				}
			}		
	}
	public static synchronized void show()//同步函数
	{
		if(tickt>0)
		{
			try{Thread.sleep(10);}catch(Exception e){}
			System.out.println("同步函数进程---"+Thread.currentThread().getName()
					+"-----sale:"+tickt--);
		}
	}
}

//测试程序代码如下:

/**
 * 验证线程锁,同步代码块和同步函数的控制通过flag旗帜来控制
 * 注意主线程需要sleep一段时间 
 * @author bing
 *
 */
public class TestMain {
	public static void main(String[] args) throws InterruptedException {
		Ticket aTicket=new Ticket();
		Thread t1=new Thread(aTicket);
		Thread t2=new Thread(aTicket);
		t1.start();//线程t1开始启动,启动的时间短,非常有可能被main主线程抢走执行权,所以让主线程休息一会
		Thread.currentThread().sleep(100);
		aTicket.flag=false;System.out.println("-------------------------------------");
		t2.start();
		System.out.println("+++++++++++++++++++");
	}
}


输出如下:
-------------------------------------
同步代码块进程---Thread-0-----sale:10
+++++++++++++++++++
同步代码块进程---Thread-0-----sale:9
同步代码块进程---Thread-0-----sale:8
同步函数进程---Thread-1-----sale:7
同步函数进程---Thread-1-----sale:6
同步函数进程---Thread-1-----sale:5
同步函数进程---Thread-1-----sale:4
同步函数进程---Thread-1-----sale:3
同步函数进程---Thread-1-----sale:2
同步函数进程---Thread-1-----sale:1
----------------------------------------小结:静态的同步方法:使用的锁是该方法所在类的字节码
文件对象。类名.class

多线程的单例设计模式
1懒汉式
package Single_Design_Pattern_Multithreading;
/**
 * 懒汉式单例模式
 * 本类描述怎么在懒汉单例模式中运用多线程同步锁
 * 方法一:可以直接将getInstance()方法声明为synchronized的 但是这样做
 * 会浪费资源 每次调用getInstance()方法时都要判断锁,所以可以按以下的方式解决
 * 也就是方法二--两次判断,延时加载
 * 
 * @author bing
 *
 */
public class LazyMan {
	private static LazyMan lm=null;
	private LazyMan(){}
	public static LazyMan getInstance()
	{/**这里的处理方式为延迟加载
		比如有线程A 进入 进入aaa判断 再进入bbb判断这时线程B启动 由aaa判断后 到
		bbb此时 有线程锁的存在 线程B没有访问权限  再次回到线程A 线程A继续执行到
		ccc这时判断后建立对象lm 线程A解锁 这时线程B再执行 判断ccc结果对象lm已经
		存在了 所以不再执行。线程C启动 判断aaa时就lm已经存在了 所以也不会再继续
		这样 就避免了对 线程锁的重复判断 节省资源---这种方式叫做两次判断,延时加载
	*/
		if(lm==null)//aaa
		{
			synchronized (LazyMan.class)//bbb
			{
				if(lm==null)//cccc
				{
					lm=new LazyMan();
				}
			}
		}
		
		
		return lm;
	}
}


//饿汉式
package Single_Design_Pattern_Multithreading;
/**
 * 饿汉式单例设计模式,不存在共享数据异常的问题 所以不用锁
 * @author bing
 *
 */
public class HungryMan_Single {
	private static final HungryMan_Single hs=new HungryMan_Single();
	private HungryMan_Single(){}
	public static HungryMan_Single getInstance()
	{
		return hs;
	}
}



====================================================================================================
死锁的问题   用以下的示例来说明死锁的问题
package Single_Design_Pattern_Multithreading;
/**
 * 懒汉式单例模式
 * 本类描述怎么在懒汉单例模式中运用多线程同步锁
 * 方法一:可以直接将getInstance()方法声明为synchronized的 但是这样做
 * 会浪费资源 每次调用getInstance()方法时都要判断锁,所以可以按以下的方式解决
 * 也就是方法二--两次判断,延时加载
 * 
 * @author bing
 *
 */
public class LazyMan {
	private static LazyMan lm=null;
	private LazyMan(){}
	public static LazyMan getInstance()
	{/**这里的处理方式为延迟加载
		比如有线程A 进入 进入aaa判断 再进入bbb判断这时线程B启动 由aaa判断后 到
		bbb此时 有线程锁的存在 线程B没有访问权限  再次回到线程A 线程A继续执行到
		ccc这时判断后建立对象lm 线程A解锁 这时线程B再执行 判断ccc结果对象lm已经
		存在了 所以不再执行。线程C启动 判断aaa时就lm已经存在了 所以也不会再继续
		这样 就避免了对 线程锁的重复判断 节省资源---这种方式叫做两次判断,延时加载
	*/
		if(lm==null)//aaa
		{
			synchronized (LazyMan.class)//bbb
			{
				if(lm==null)//cccc
				{
					lm=new LazyMan();
				}
			}
		}
		
		
		return lm;
	}
}


//饿汉式
package Single_Design_Pattern_Multithreading;
/**
 * 饿汉式单例设计模式,不存在共享数据异常的问题 所以不用锁
 * @author bing
 *
 */
public class HungryMan_Single {
	private static final HungryMan_Single hs=new HungryMan_Single();
	private HungryMan_Single(){}
	public static HungryMan_Single getInstance()
	{
		return hs;
	}
}

====================================================================================================
死锁的问题   用以下的示例来说明死锁的问题
package DemoSynchronized;

public class Ticket implements Runnable{
	private int tickt=100;
	Object obj = new Object();
	public boolean flag=true;
	public void run()//同步代码块
	{	
		if(flag)
		{
			while(true)
			{
				synchronized (obj)//这里是同步代码块中有同步函数,注意锁是不同的
				{
					show();
				}
				
			}
		}else
			{
				while(true)
				{
					show();
				}
			}
		
	}
	
	public synchronized void show()//同步函数这里的锁是this
	{	//注意这里是同步函数里面有同步代码块而且两者的锁是不同的
		synchronized(obj)//这里的锁是obj
		{
			if(tickt>0)
			{
				try{Thread.sleep(10);}catch(Exception e){}
				System.out.println("同步函数进程---"+Thread.currentThread().getName()
						+"-----sale:"+tickt--);
			}
		}
		
	}
}
//测试程序代码如下:
package DeadLock;

import DemoSynchronized.Ticket;

/**
 * 死锁:
 * 同步中嵌套同步
 * @author bing
 *
 */
public class TestMain {
	public static void main(String[] args) throws InterruptedException {
		Ticket aTicket=new Ticket();
		Thread t1=new Thread(aTicket);
		Thread t2=new Thread(aTicket);
		t1.start();//线程t1开始启动,启动的时间短,非常有可能被main主线程抢走执行权,所以让主线程休息一会
		Thread.currentThread().sleep(16);
		aTicket.flag=false;System.out.println("-------------------------------------");
		t2.start();
	}
}
//输出结果:输出过程中卡住  因为两个锁互相争夺

===========================================================================================
线程间通信的安全问题:
线程A对资源R进行加操作线程B对资源R进行减操作 如何同步 如何同步时安全操作 示例代码如下:
package DemoSynchronized;

public class Ticket implements Runnable{
	private int tickt=100;
	Object obj = new Object();
	public boolean flag=true;
	public void run()//同步代码块
	{	
		if(flag)
		{
			while(true)
			{
				synchronized (obj)//这里是同步代码块中有同步函数,注意锁是不同的
				{
					show();
				}
				
			}
		}else
			{
				while(true)
				{
					show();
				}
			}
		
	}
	
	public synchronized void show()//同步函数这里的锁是this
	{	//注意这里是同步函数里面有同步代码块而且两者的锁是不同的
		synchronized(obj)//这里的锁是obj
		{
			if(tickt>0)
			{
				try{Thread.sleep(10);}catch(Exception e){}
				System.out.println("同步函数进程---"+Thread.currentThread().getName()
						+"-----sale:"+tickt--);
			}
		}
		
	}
}
//测试程序代码如下:
package DeadLock;

import DemoSynchronized.Ticket;

/**
 * 死锁:
 * 同步中嵌套同步
 * @author bing
 *
 */
public class TestMain {
	public static void main(String[] args) throws InterruptedException {
		Ticket aTicket=new Ticket();
		Thread t1=new Thread(aTicket);
		Thread t2=new Thread(aTicket);
		t1.start();//线程t1开始启动,启动的时间短,非常有可能被main主线程抢走执行权,所以让主线程休息一会
		Thread.currentThread().sleep(16);
		aTicket.flag=false;System.out.println("-------------------------------------");
		t2.start();
	}
}
//输出结果:输出过程中卡住  因为两个锁互相争夺

===========================================================================================
线程间通信的安全问题:
线程A对资源R进行加操作线程B对资源R进行减操作 如何同步 如何同步时安全操作 示例代码如下:
package InOut_Demo;
/**
 * 线程间通信的示例代码
 * 线程间通信,其实就是多个线程在操作同一个资源,但是操作的动作是不同的
 * @author bing
 *
 */
public class TestMain {
	public static void main(String[] args) {
		Res r =new Res();
		Input in=new Input(r);
		OutPut ou = new OutPut(r);
		Thread t1=new Thread(in);
		Thread t2=new Thread(ou);
		t1.start();
		t2.start();
	}
	
	
}

//资源R代码如下
package InOut_Demo;
/**
 * 资源Res,Input和OutPut的操作对象
 * @author bing
 *
 */
public class Res {
	private String name;
	private String sex;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
}

//写操作代码如下
package InOut_Demo;
/**
 * 对资源R进行写操作
 * @author bing
 *
 */
public class Input implements Runnable{
	private Res r;
	Input(Res r)
	{this.r=r;}
	public void run()
	{	int x=0;
		while(true)
		{
			synchronized (r) {
				if(x==0){r.setName("mike");r.setSex("man");}
				if(x==1){r.setName("王语嫣");r.setSex("女女");}
			}
			
			x=(x+1)%2;
			
		}
		
	}
}

//输出操作代码如下:
package InOut_Demo;
/**
 * 输出资源R的内容
 * @author bing
 *
 */
public class OutPut implements Runnable{
	private Res r;
	public OutPut(Res r){this.r=r;}
	
	public void run()
	{
		while(true)
		{
			synchronized(r){System.out.println(r.getName()+r.getSex());}
			
		}
		
	}
}
//测试程序代码如下
package InOut_Demo;
/**
 * 线程间通信的示例代码
 * 线程间通信,其实就是多个线程在操作同一个资源,但是操作的动作是不同的
 * @author bing
 *
 */
public class TestMain {
	public static void main(String[] args) {
		Res r =new Res();
		Input in=new Input(r);
		OutPut ou = new OutPut(r);
		Thread t1=new Thread(in);
		Thread t2=new Thread(ou);
		t1.start();
		t2.start();
	}
	
	
}


经过测试  输出有序 说明线程间通信的安全问题解决
输出如下:
mikeman
mikeman
mikeman
王语嫣女女
王语嫣女女
王语嫣女女
==========================================================================================
等待唤醒机制
---接上个例子 要求 男女输出交替进行 也就是 写--男--输出--男---写--女---输出---女
资源类如下:
public class Res {
	public String name;
	public String sex;
	public boolean flag=false;//旗帜变量用来控制是写资源还是输出资源
}
//写方法类如下:
public class Input implements Runnable{
	public Res r;
	private int x=0;
	Input(Res r){this.r=r;}
	
	public void run() {
		while(true)
		{
			synchronized(r)
			{
				//如果旗帜为真,则等待 等待需要与锁一致
				if(r.flag){try{r.wait();}catch(Exception e){System.out.println("Input wait 异常");}}
				//如果旗帜为假  则写入资源
				if(x==0){r.name="mike";r.sex="man";}
				else{r.name="周芷若";r.sex="女女";}
				x=(x+1)%2;
				//写完资源后  资源设置为真
				r.flag = true;
				r.notify();		//唤醒,需要与锁一致		
			}
		}
	}
}

//输出资源类如下:
package Wait_WakeUp_right;

public class OutPut implements Runnable{
	private Res r;
	OutPut(Res r){this.r=r;}
	public void run()
	{
		while(true)
		{
			synchronized(r)
			{
				if(!r.flag)//如果资源为假 则等待 
				{
					try{r.wait();}catch(Exception e){System.out.println("output wait 出错");}
				}
				//如果资源为真 则输出资源
				System.out.println(r.name+"。。。。"+r.sex);
				r.flag = false;//输出后  资源设置为假
				r.notify();//唤醒
			}
		}
	}
	
}

//测试程序如下:
public class TestMain {

	/**wait;
	 * notify;
	 * notifyALl;  都在同步中使用,因为要对持有监视器(锁)的线程操作。
	 * 所以都要使用在同步中,因为只有同步才有锁。
	 * 为什么这些操作线程的方法要定义在object类中?
	 * 因为这些方法在操作同步中线程时,都必须要标识他们所操作的线程持有的锁
	 * 只有同一个锁上的被等待线程可以被同一个锁上的线程notify唤醒,不可以对不同
	 * 锁中的线程进行唤醒
	 * 
	 * 也即是说等待和唤醒必须是同一把锁。
	 * 而锁可以是任意对象,可以被任意对象调用的方法就定义在Object中
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		Res r=new Res();
		Input in=new Input(r);
		OutPut ou=new OutPut(r);
		Thread t1=new Thread(in);
		Thread t2=new Thread(ou);	
		t1.start();
		t2.start();

	}

}

输出结果如下:
mike。。。。man
周芷若。。。。女女
mike。。。。man
周芷若。。。。女女
mike。。。。man
周芷若。。。。女女
mike。。。。man
周芷若。。。。女女
mike。。。。man
周芷若。。。。女女
mike。。。。man-----------结果有序 而且交替输出


分享到:
评论

相关推荐

    JAVA 多线程学习笔记

    这篇学习笔记将深入探讨Java多线程的核心概念、实现方式以及相关工具的使用。 一、多线程基础 1. 线程与进程:在操作系统中,进程是资源分配的基本单位,而线程是程序执行的基本单位。每个进程至少有一个主线程,...

    Java多线程学习笔记

    ### Java多线程学习笔记 #### 一、线程的基本概念 在计算机科学中,**线程**(Thread)是程序执行流的最小单位。一个标准的程序只能做一件事情,而通过多线程技术,可以让程序同时处理多个任务。在Java中,线程是...

    UNIX多线程学习笔记

    【UNIX多线程学习笔记】 在UNIX操作系统中,多线程是一种重要的编程模型,它允许多个执行流在单个进程中并发运行。多线程带来了许多优势,包括提高应用程序响应速度,充分利用多CPU系统的资源,以及优化程序结构,...

    C++多线程学习笔记1

    这份"C++多线程学习笔记1"涵盖了基础到进阶的多线程概念,旨在帮助初学者快速掌握这一关键技能。 首先,C++11引入了对多线程的支持,引入了`<thread>`库,使得创建和管理线程变得简单。创建一个新的线程可以使用`...

    java基础:多线程学习笔记

    java基础:多线程学习笔记

    多线程 学习笔记.md

    多线程 学习笔记.md

    java学习笔记2(多线程)

    java学习笔记2(多线程)java学习笔记2(多线程)

    Python3的多线程学习笔记[定义].pdf

    本篇学习笔记主要涵盖了线程基础、threading模块的使用以及线程同步控制。 首先,线程是操作系统分配CPU执行时间的基本单位,一个进程可以包含多个线程。在Python3中,线程的状态主要包括新建、就绪、运行、死亡、...

    java多线程学习笔记

    这篇文档和对应的源代码 博文链接:https://interper56-sohu-com.iteye.com/blog/172303

    多线程学习笔记,关于创建线程,删除线程等相关指令的应用。

    在计算机科学中,多线程是一种编程模型,允许一个应用程序同时执行多个任务。这提高了系统的效率,特别是对于处理大量并发操作的情况。以下是一些关于多线程的重要知识点,特别是关于在Linux和Windows环境下创建和...

    多线程学习笔记.docx

    在多线程编程中,进程和线程是两个核心概念。进程是操作系统资源分配的基本单位,每个独立执行的程序都对应一个进程。而线程则是程序执行的最小单元,是进程内部的一条执行路径。多线程是指在一个应用程序中存在多个...

    java多线程学习笔记02(csdn)————程序.pdf

    在这个学习笔记中,主要讨论了Java中的线程同步机制,包括volatile关键字、synchronized以及Lock接口,特别是ReentrantLock的使用。 首先,对于线程1和线程2的疑惑,调试(debug)模式并不能改变线程的执行顺序。...

    JAVA多线程学习笔记整理(csdn)————程序.pdf

    Java多线程是Java编程中的核心概念,它允许并发执行多个任务,提高程序的执行效率。以下是关于Java多线程的详细知识点: 1. **创建线程** - **继承Thread类**:创建一个新的类,该类继承自Thread类,并重写run()...

    java多线程学习笔记之自定义线程池

    Java多线程学习笔记之自定义线程池 本篇文章主要介绍了Java多线程学习笔记之自定义线程池,通过深入了解ThreadPoolExecutor这个核心类,我们可以自定义线程池,满足不同的线程池需求。 Java多线程学习笔记之自定义...

    java线程学习笔记

    Java 线程学习笔记 Java 线程创建有两种方法: 1. 继承 Thread 类,重写 run 方法:通过继承 Thread 类并重写 run 方法来创建线程,这种方法可以使线程具有自己的执行逻辑。 2. 实现 Runnable 接口:通过实现 ...

    Java并发编程学习笔记 pdf 多线程编程

    Java并发编程学习笔记,研究JAVA并发多线程编程的一本教程,使用并发技术可以开发出并行算法,充分利用多处理器的计算能力,避免硬件资源浪费。目前,在JAVA并发编程方面的论述系统且内容详实的技术资料不太多,Java...

Global site tag (gtag.js) - Google Analytics