------- android培训、java培训、期待与您交流! ----------
1.进程:是一个正在执行的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。线程就是进程中一个独立的控制单元。线程在控制着进程的执行。一个进程中至少有一个线程。jvm启动时,会有一个进程java.exe,该进程中至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中,称为主线程。
2.创建线程
方法1.继承Thread类
步骤:
(1)定义类继承Thread
(2)复写Thread类中的run方法:将自定义代码存储在run方法中,让线程运行。Thread类用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法,即Thread类中的run方法用于存储线程要运行的代码。
(3)调用线程start方法:启动线程和调用run方法
currentThread():获取当前线程的对象。
方法2:实现Runable方法
步骤:
(1)定义类实现Runable接口
(2)覆盖Runable接口中的run方法,将线程要运行的代码存储在该run方法中。
(3)通过Thread类建立线程对象
(4)将Runable接口的子类对象作为实际参数传递给Thread类的构造函数。因为自定义的run方法所属的对象是Runable接口的子类对象,所以要让线程去指定指定对象的run方法,就必须明确该run方法所属的对象。
(5)调用Thread类的start方法开启并调用Runable接口子类的run方法。
实现方式和继承方式的区别:
实现方式好处:避免的单继承的局限性,在定义线程时,建议使用实现方式。
继承Thread:线程代码存放Thread子类run方法中
实现Runable:线程代码存在接口子类的run方法中。
3.同步
当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。解决办法:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可参与执行。
synchronized(对象)
{
需要被同步的代码;
}
对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取cpu执行权也进不去。
同步的前提:必须要有两个或两个以上的线程,必须是多个线程使用同一个锁。必须保证同步中,只能有一个线程在运行。
好处:解决多线程的安全问题
弊端:多个线程需要判断,较为消耗资源,容易死锁。
同步代码块使用的锁是任意对象。
同步函数使用的锁是this
同步函数被静态修饰锁是类名.class
4.线程间通信
等待/唤醒机制。当多个生产者消费者出现时,需要让获取执行权的线程判断标记。通过while完成。需要将对方的线程唤醒,仅仅用notify是不可以的,因为有可能出现只唤醒本方,有可能导致所有线程等待。所以可以通过notifyAll来完成。
JDK1.5版本提供了一些新的对象,优化了等待唤醒机制。
(1)将synchronized替换成了Lock接口。获取锁:lock();释放锁:unlock();释放的动作一定要执行,通常定义在finally中。获取Condition对象:newCondition();
(2)将Object中的wait、notify、notifyAll方法替换成了Condition的await、single、singleAll
wait和sleep的区别:wait是既释放cpu执行权也释放同步中锁;sleep只是释放cpu执行权。
5.停止线程
run方法结束,run方法中通常定义循环,指定控制住循环线程即可结束。
定义结束标记
当线程处于冻结状态,没有执行标记,程序一样无法结束。这时可以循环,正常退出冻结状态,或者强制结束冻结状态:interrupt(),会发生InterruptedException异常。
6.多线程练习:卖票系统,多个窗口同时卖票
public class TicketTest {
/**
* 简单的卖票系统,多个窗口同时卖票
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Ticket t=new Ticket();//创建Ticket对象t
Thread t1=new Thread(t);//创建Thread将t作为参数传进去
Thread t2=new Thread(t);//创建Thread将t作为参数传进去
Thread t3=new Thread(t);//创建Thread将t作为参数传进去
Thread t4=new Thread(t);//创建Thread将t作为参数传进去
t1.start();//开启线程1
t2.start();//开启线程2
t3.start();//开启线程3
t4.start();//开启线程4
}
}
//新建Ticket类实现Runnable,复写run方法
class Ticket implements Runnable{
private int tick=100;
Object obj=new Object();//任意对象,锁功能
public void run()//复写run方法,放多线程运行的代码
{
while(true)
{
synchronized(obj)//同步代码块锁为任意对象
{
if(tick>0)
System.out.println(Thread.currentThread().getName()+"...sale:"+tick--);
}
}
}
}
7.写一个死锁代码(同步中嵌套同步)
public class DeadLockTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
try
{
Thread.sleep(10);
}
catch(Exception e)
{}
t.flag=false;
t2.start();
}
}
//建Ticket类实现Runnable,复写run方法
class Ticket implements Runnable{
private int tick=100;
Object obj=new Object();
boolean flag=true;
public void run()
{
if(flag)
{
while(true)
{
synchronized(obj)
{
show();//同步中嵌套同步
}
}
}
else
while(true)
show();
}
public synchronized void show()
{
synchronized(obj)
{
if(tick>0)
{
System.out.println(Thread.currentThread().getName()+"...code:"+tick--);
}
}
}
}