黑马程序员
----------------------
线程:正在进行中的程序。每一个进程执行都有一个执行的顺序。该顺序就是一个执行路径,或者叫一个控制单元。线程就是进程中的一个独立单元,线程控制着进程的执行,一个进程中至少有一个线程。
特点:线程是程序中的控制单元或者叫执行路径。
Java vm启动时候会有一个进程java.exe,该进程至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中。该线程称之为主线程。
创建线程的第一种方式:继承Thread
步骤:1,定义类继承Thread类
2,复写Thread中的Run方法
目地:将自定义的代码块存储在Run方法中,让线程运行。
3,调用线程的Start方法,该法有两个作用,第一个是启动线程,第二个是调动Run方法。
发现运行结果的没一次都不同,因为多个线程都获取CPU的执行权,CPU到底执行谁,运行谁。明确一点,在某一个时刻,只能有一个程序在运行。(多核除外)CPU在做着快速的切换,以达到看上去是同时运行的效果。我们可以形象把多线程的运行行为在互相抢夺CPU的执行权。
这就是多线程的一个特点:随机性。谁抢到谁执行,至于执行多长,CPU说的算。
Demo d=new Demo();创建好一个线程
d.Start();开启线程并执行该线程的Run方法
d.run();仅仅是对象调用方法,而线程创建了,并没有运行。
没有执行资格的情况下就是冻结状态。
有执行资格的就是临时状态。
既有资格又有执行权的就是运行状态。
Static Thread CurrentThread();获取当前对象。
getName();获取当前线程的名称。
设置线程名称:setName或者构造函数。
使用static可以共享一个线程(一般不用)
实现线程的步骤
1 、实现Runnable接口
2、覆盖Runnable接口的Rund方法
将线程要运行的代码放在该Run方法中。
3、通过Thread类建立线程对象。
4、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
为什么要将Runnable接口中的子类对象传递给Thread类的构造函数。因为,自定义的Run方法所属的对象是Runnable接口子类的对象。
所以要让线程执行指定对象的Run方法。就必须明确该Run方法所属的对象。
5、调用Thread类的start方法开启线程并调用Runable接口子类的Run方法
线程实现方式和继承方式有什么区别呢?
实现的好处:是避免了单继承的局限性.
在定义线程的时候,建立使用实现方式。
两种方式区别:
继承Thread:线程代码存放在Thread子类Run方法中。
实现Runnable,线程代码存在接口的子类Run方法中
同步:A线程要请求某个资源,但是此资源正在被B资源使用,因为同步机制的存在,A线程请求不到,怎么办,A只能等待下去。
异步:A线程要请求某个资源,但是此资源正在被B线程使用,因为没有同步机制的存在,A线程任然请求的到,A线程无需等待。
死锁:就是说,你持有一个锁,我也持有一个锁,我要到你里面运行,你要到我里面,你不放你的锁要到我里面去,我不放我的锁要到你里面去。
同步中嵌套同步。
同步函数用的哪一个锁呢?函数需要被对象调用。那么函数都要有一个所属对象引用。就是this所以同步函数使用的锁是this 通过该程序进行验证。
使用两个线程来买票。一个线程在同步代码块中。一个程序在同步函数中。都在执行买票动作。
如果同步函数被静态修饰后,使用的锁是什么呢?
通过验证,发现不在是this.因为静态方法也不可以定义this.
态进内存是,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象。
public class Ticket2 {
public static void main(String[] args) {
TciktDemos tc = new TciktDemos();
Thread t1 = new Thread(tc);
Thread t2 = new Thread(tc);
t1.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
tc.flag=false;
t2.start();
}
}
class TciktDemos implements Runnable {
private int tick = 100;
//Object obj = new Object();
boolean flag=true;
public void run() {
if(flag){
while (true) {
synchronized (this) {
if (tick > 0) {
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName()
+ ".....code:" + tick--);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
}else
while(true)
this.show();
}
public synchronized void show() {
if (tick > 0) {
try {
Thread.sleep(10);
System.out.println(Thread.currentThread().getName()
+ ".....show...:" + tick--);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
死锁代码块:
public class DeadLockTest {
public static void main(String[] args) {
Thread t1=new Thread(new test(true));
Thread t2=new Thread(new test(false));
t1.start();
t2.start();
}
}
class test implements Runnable{
private boolean flag;
test(boolean flag){
this.flag=flag;
}
public void run() {
if(flag){
while(true){
synchronized (MyLock.locka) {
System.out.println("if locka");
synchronized (MyLock.lockb) {
System.out.println("if lockb");
}
}
}
}else{
while(true){
synchronized (MyLock.lockb) {
System.out.println("else lockb");
synchronized (MyLock.locka) {
System.out.println("else locka");
}
}
}
}
}
}
class MyLock{
static Object locka=new Object();
static Object lockb=new Object();
}
单列设计模式:
class Single{
private static final Single s=new Single();
private Single(){
}
public static Single getInstance(){
return s;
}
}
懒汉式与饿汉式有什么不同?
懒汉式的特点在于延迟加载, 懒汉式延迟加载有没有问题,有
怎么解决,加同步的方式解决,用同步代码块和同步函数都行,但是稍微有些低效。
双重判断可以解决效率问题,加同步的时候,使用的锁是那个该类所属的字节码对象。
*/
class Single{
//懒汉式 ,在多线程访问下会出现安全隐患。懒汉式加了同步会比较低效
private static Single s=null;
private Single(){
}
/*
延迟加载,对象被延迟
s是共享数据,如果多个线程并发访问getInstance,是有可能的!
*/
public static Single getInstance(){
//用双重判断的问题解决了懒汉式的效率问题
if(s==null){
synchronized(Single.class){
if(s==null){
s=new Single();
}
}
}
return s;
}
}
public class SingleDemo {
public static void main(String[] args) {
}
}
/*
线程通讯:
其实就是多个线程在操作同一个资源。
但是操作的动作不同。
wait:
notify();
notifyAll();
都是用在同步中,因为要对持有监视器(锁)的线程操作。
所以在使用同步中,因为只有同步才具有锁的概率。
为什么这些操作线程的方法要定义在Object类中呢?
因为这些方法在操作同步线程时,都必须要标示他们所操作线程只有的锁,只有同一个
锁上的被等待线程,可以被同一锁上的notify唤醒。
不可以对不同锁中的线程进行唤醒
也就是说,等待和唤醒必须是同一个锁,而锁可以是任意对象,所以可以被任意对象调用调用的方法定义Object类中。
*/
class Res2{
private String name;
private String sex;
private boolean flag=false;
public synchronized void set(String name,String sex){
if(flag)
try {
this.wait();
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.name=name;
this.sex=sex;
flag=true;
this.notify();
}
public synchronized void out(){
if(!flag)
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+"........"+sex);
this.flag=false;
this.notify();
}
}
class Input2 implements Runnable{
private Res2 r;
Input2(Res2 r){
this.r=r;
}
public void run() {
int x=0;
while(true){
if(x==0){
r.set("mike", "man");
}else{
r.set("莉莉", "女女女女女");
}
x=(x+1)%2;
}
}
}
class Output2 implements Runnable{
private Res2 r;
Output2(Res2 r){
this.r=r;
}
public void run() {
while(true){
r.out();
}
}
}
public class InpntOutputDemo2 {
public static void main(String[] args) {
Res2 r=new Res2();
new Thread(new Input2(r)).start();
new Thread(new Output2(r)).start();
}
}
public class ProducerConsumerDemo2 {
public static void main(String[] args) {
Resource res=new Resource();
Producer pro=new Producer(res);
Consumer con=new Consumer(res);
Thread t1=new Thread(pro);
Thread t2=new Thread(pro);
Thread t3=new Thread(con);
Thread t4=new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
/*
JDK1.5中提供了多线程升级解决方案。
将同步中synchronized替换成现实lock操作。
将object中的wait,notify,notifyAll,替换了Condition对象。
该对象可以通过Lock锁获取。
1.5的新特性实现了Lock接口和Condition接口。
该实例中实现了本方只唤醒对方的操作。
1.5版本后,提供了显示的锁机制,以及显示的锁对象上的等待唤醒操作机制,同封装了等待唤醒。一个锁可以对应
多个Condition。
*/
class Resources{
private String name;
private int count=1;
private boolean flag=false;
private Lock lock=new ReentrantLock();
private Condition condition_pro=lock.newCondition();
private Condition condition_con=lock.newCondition();
public synchronized void set(String name){
lock.lock();
try{
while(flag)
condition_pro.wait();//t1 t2
this.name=name+"....."+count++;
System.out.println(Thread.currentThread().getName()+".....生产者....."+this.name);
this.flag=true;
condition_con.signalAll();
}catch(Exception ex){
ex.printStackTrace();
}finally{
lock.unlock();//释放一次解锁动作。
}
}
public synchronized void out(){
lock.lock();
try{
while(!flag)
condition_con.wait();
System.out.println(Thread.currentThread().getName()+".....消费者.............."+this.name);
this.flag=false;
condition_pro.signalAll();
}catch(Exception ex){
ex.printStackTrace();
}finally{
lock.unlock();
}
}
}
class Producers implements Runnable{
private Resources res;
Producers(Resources res){
this.res=res;
}
public void run() {
while(true){
res.set("商品");
}
}
}
class Consumers implements Runnable{
private Resources res;
Consumers(Resources res){
this.res=res;
}
public void run() {
while(true){
res.out();
}
}
}
/*
stop停止方法已过时。
如何停止线程。
只有一种,run方法结束。
开启多线程运行,运行代码通常是循环结构。
只要控制住循环,就可以让run方法结束,也就是线程结束。
特性情况:
当线程处于了冻结状态、
就不会读取标记,那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。
Thread类提供该方法interrupt()
*/
public class StopThreadDemo {
public static void main(String[] args) {
StopThread st=new StopThread();
Thread t1=new Thread(st);
Thread t2=new Thread(st);
//t1.setDaemon(true);//守护线程方法。
//t2.setDaemon(true);
t1.start();
t2.start();
int num=0;
while(true){
if(num ++ ==60){
//st.changeFlag();
t1.interrupt();
t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"main......."+num);
}
System.out.println("over");
}
}
class StopThread implements Runnable{
private boolean flag=true;
public synchronized void run() {
while(flag){
try {
wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+".....Execption");
flag=false;
}
System.out.println(Thread.currentThread().getName()+".....run");
}
}
public void changeFlag(){
flag=false;
}
}
----------------------android培训、java培训、期待与您交流! ------------------
详细请查看:http://edu.csdn.net/heima