---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
进程与线程的关系
进程:
是一个正在执行中的程序
每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元
线程:
就是进程中一个独立的控制单元
线程在控制着进程的执行
一个进程中至少有一个线程
例如:jvm启动的时候会有一个进程java.exe
该进程中至少有一个线程负责java程序的执行
而且这个线程运行的代码存在于main方法中
该线程称之为主线程
创建线程的两种方法
一 创建线程-继承Thread类
步骤:
1、定义类继承Thread
2、重写run方法,目的是将自定义的代码存储在run方法中,让线程运行
3、创建对象调用start方法用于:(1)启动线程 (2)调用run方法
class Test extends Thread
{
public void run()
{
System.out.println("test run");
}
}
class Demo
{
public static void main(String[] args)
{
Test t = new Test();
t.start();
}
}
<span style="font-size:14px;"></span>
Threed用于描述线程
而Thread中run方法用于存放执行代码
所以继承Thread的同时要覆盖run方法
下面运行多个线程并发的情况:
class Test extends Thread
{
String name;
Test(String name)
{
this.name = name;
}
public void run()
{
for(int x = 0; x<90; x++)
{
System.out.println(name +"…run…"+x);
}
}
}
class Demo
{
public static void main(String[] args)
{
Test t1 = new Test("one");
Test t2 = new Test("two");
t1.start();
t2.start();
for(int x = 0; x<90; x++)
{
System.out.println("main run"+x);
}
}
}
发现运行结果每一次都不同
因为多个线程都获取CPU的执行权,CPU执行到谁,谁就运行
明确一点,在某一个时刻,只能有一个程序在运行(多核除外)
CPU在做着快速切换,以达到看上去是同时运行的结果
我们可以形象的把多线程的运行行为看作在互相抢夺CPU的执行权
这就是多线程的一个特性:随机性,谁抢到谁执行,至于执行多长时间,CPU说的算
线程运行状态:
被创建------->运行<---------临时状态(阻塞)-------->冻结
|
|
消亡
临时状态(阻塞)包含的意思:有运行资格没有执行权
二 创建线程-实现Runnable接口
也是第二种创建线程的方式:
步骤:
1、定义类实现Runnable接口
2、覆盖Runnable接口中的run方法
3、通过Thread类建立线程对象
4、将Runnable接口的子类的对象作为参数传递给Thread类的构造函数
5、调用Thread类的start方法开启线程并调用Runnable接口子类的run方法
好处:
避免了单继承的局限性,也就是说继承是位置可以腾出来。
在定义线程时,建议使用实现方式
售票的例子:
class Ticket implements Runnable
{
private int ticket = 100;
public void run()
{
while(true)
{
if(ticket >0)
System.out.println(Thread.currentThread().getName()+"......"+ticket--);
}
}
}
class Demo
{
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();
}
}
多线程的安全问题
问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行一部分,
还没有执行完,另一个线程参与进来执行,导致共享数据的错误。
解决方法:
对多条操作共享数据的语句,只能让一个线程都执行完,
在执行过程中,其他线程不可以参与进来
同步代码块解决此问题
synchronized(对象)
{
需要被同步的代码
}
示例:
class Ticket implements Runnable
{
private int ticket = 100;
Object obj = new Object();
public void run()
{
while(true)
{
synchronized(obj)
{
if(ticket >0)
System.out.println(Thread.currentThread().getName()+"..."+ticket--);
}
}
}
}
对象如同锁,持有锁的线程可以在同步中执行
没有持有锁的线程即使获得CPU的执行权,也进不去,因为没有获得锁
同步前提:
必须要有两个或者两个以上的线程
必须是多个线程使用一个锁
好处:解决了多线程的安全问题
弊端:多个线程需要判断锁,较为消耗资源,低效
多线程-同步函数
同步函数写法:
public synchronized void add(int n)
{
}
售票的例子可以改为:
class Ticket implements Runnable
{
private int ticket = 100;
public void run()
{
while(true)
{
show();
}
}
public synchronized void show()
{
if(ticket >0)
System.out.println(Thread.currentThread().getName()+""+ticket--);
}
}
<span style="font-family:Times New Roman;font-size:14px;"> </span>
多线程-单例模式-懒汉式
比较经典的多线程处理方式
class Single
{
private static Single single = null;
private Single()
{
}
public static Single getInstance()
{
//提高效率,非空的时候已经不需要判断锁了
if(single == null)
{
synchronized(Single.class)
{
if(single == null)
s = new Single();
}
}
return s;
}
}
多线程-死锁
class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
}
public void run()
{
if(flag)
{
while(true)
{
synchronized(Lock.locka)
{
System.out.println("if locka");
synchronized(Lock.lockb)
{
System.out.println("if lockb");
}
}
}
}
else
{
while(true)
{
synchronized(Lock.lockb)
{
System.out.println("else lockb");
synchronized(Lock.locka)
{
System.out.println("else locka");
}
}
}
}
}
}
class Lock
{
Static Object locka = new Object();
Static Object lockb = new Object();
}
虽然看起来很乱,但是基本意思就是当出现同步锁嵌套的情况,会很容易出现死锁
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com