一线程的概念
进程:是一个正在执行中的程序,每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
线程:就是进程中的一个独立的控制单元;线程在控制着进程的执行。
Java虚拟机启动的时候会有一个进程java.exe.该进程中至少一个线程负责java程序的执行。而且这个线程运行的代码存在于main方法中,该线程称之为主线程,每个进程中至少有一个线程。
二线程的创建
第一种方式:创建线程继承Thread类,
步骤:
1,定义类继承Thread。
2,复写Thread类中的run方法。
3,调用线程的start方法,该方法两个作用:启动线程,调用run方法。
如下代码:
class MyThread extends Thread
{
}
class MyThreadDemo
{
}
步骤:
1,设计类实现Runnable接口实现该接口里的run方法;
2,创建该类的是两年作为参数传如Thread类的构造方法;
如下代码:
class MyThread implements Runnable{
}
然后在创建启动线程
new(new MyThread()).start();
采用继承Thread类方式:
(1)优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this,即可获得当前线程。
(2)缺点:因为线程类已经继承了Thread类,所以不能再继承其他的父类。
采用实现Runnable接口方式:
(1)优点:线程类只是实现了Runable接口,还可以继承其他的类。在这种方式下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将CPU代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
(2)缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。
对象如同锁。持有锁的线程可以在同步中执行。
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
最后总结一下单例设计模式:
懒汉设计模式如下:
class Single
{
采懒汉设计模式时候存在安全隐患,当线程执行到A处的时候执行权被剥夺了停了了下来此时另一个线程就可能执行到此处这样就可能创建多个Single对象引发错误;这种设计必须同步处理如下代码:
}
另外一种设计模式是饿汉式这种设计安全性比较高
class Single
{
}
四
同步的前提:
1,必须要有两个或者两个以上的线程。
2,必须是多个线程使用同一个锁。
必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源
加锁对象是Object的实例;也可以通过加锁函数来实现同步此时的加锁对象是调用该函数的this,静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class,如下代码:
取钱的步骤:
1,用户输入帐号密码系统判断用户的账户密码是否匹配。
2,用户输入取款金额。
3,系统判断账户余额是否大于取款金额。
4,如果大于就成功否则就失败。
我们按上面的流程去编写取款程序,我们用两条线程来模拟取钱操作:
public class Account
{
}
接下来提供一个取钱的线程类,执行账户,取钱数量进行操作,逻辑是余额不足时候无法提取现金,当余额足够时候吐出钞票,余额减少。
public class DrawThread extends Thread
{
}
现在启动2个线程该账户里取钱:
public class TestDraw
{
}
去掉上面的注释部分代码在多次运行后会发现最后余额会会出现负值的情况,这就是多线程并发访问共享资源是的错误
解决办法一 同步代码块:
synchronized(obj){} obj就是同步监视器,该代码的含义是线程访问同步代码前必须获得同步监视器的锁定。
Java程序中允许使用任何对象来做同步监视器,但是为了阻止多线程对同一资源的访问,必须使用的是同一个监视器。下面我们考虑用account作为同步监视器代码修改如下:
public class DrawThread extends Thread
{
}
上面的程序使用synchronized实现了同步,两个线程必须使用同步锁所以保证了共享资源的安全性
除此之外还可以使用同步方法,使用同步方法的锁是this对象,静态同步方法使用的锁是该方法对应类的Class对象这里不再演示程序。
java1.5以后加入了锁对象更加方便了控制多线程同步问题通常使用Lock对象的代码如下:
class x{
}
五 死锁
class A
{
}
class B
{
}
public class DeadLock implements Runnable
{
}
Java虚拟机没有提供死锁的解决办法,所以我们写程序要避免死锁的发生。
六 线程的协同通信的问题
如下代码:
class Res
{
}
class Input implements Runnable
{
}
class Output implements Runnable
{
}
class
{
}
这里解释下几个方法
wait():导致当前线程等待,直到其他线程调用该同步监视器的notify方法或者notifyAll方法来唤醒该线程。
notify()唤醒此同步监视器上的等待的单个线程,如果有多个线程在同步器上等待就唤醒其中一个。
notifyAll():唤醒在次同步监视器上等待的所有线程