---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
进程和线程的定义:
进程:一个正在执行中的程序,每一个进程执行都有一个执行顺序,该顺序就是一个执行路径,或者叫一个控制单元。一个进程中至少有一个线程。
线程:进程中的一个控制单元,控制着进程执行。
Java 虚拟机启动时会有一个进程java.exe,该进程中至少有一个线程负责java程序执行,该线程运行的代码存在于main方法中,该线程成为主线程。细节说明,jvm启动时不知启动一个线程,还有负责垃圾回收机制的线程。
创建线程的两种方式:
继承Thread类覆盖run方法和实现Runnable接口覆盖run方法。
第一种:
1、定义类继承Thread类
2、覆盖Thread类中的run方法
目的:将自定义代码存储在run方法。让线程运行。
3、调用线程的start方法
目的:该方法两个作用:启动线程,调用run方法
创建线程第二种方法:实现Runnable接口
1、定义实现Runnable接口
2、覆盖Runnable接口中run方法
3、通过Thread建立线程对象
4、将Runnable接口子类对象作为参数传递给Thread类的构造函数
5、调用Thread类的start方法开启线程并调用Runnable接口子类run方法
多线程实现方式好处:
避免单继承局限性,定义线程时建立使用实现方式。
两种方式区别:
继承Thread类,线程运行代码存放于Thread子类run方法中,实现Runnable接口,线程运行代码存放于Runnable接口子类run方法中
class Demo extends Thread
{
public void run()
{
for(int x=0; x<60; x++)
System.out.println("demo run----"+x);
}
}
class ThreadDemo
{
public static void main(String[] args)
{
//for(int x=0; x<4000; x++)
//System.out.println("Hello World!");
Demo d = new Demo();//创建好一个线程。
//d.start();//开启线程并执行该线程的run方法。
d.run();//仅仅是对象调用方法。而线程创建了,并没有运行。
for(int x=0; x<60; x++)
System.out.println("Hello World!--"+x);
}
}
/*
练习:
创建两个线程,和主线程交替运行。
线程都有自己默认的名称。
Thread-编号 该编号从0开始。
static Thread currentThread():获取当前线程对象。
getName(): 获取线程名称。
设置线程名称:setName或者构造函数。
*/
class Test extends Thread
{
//private String name;
Test(String name)
{
//this.name = name;
super(name);
}
public void run()
{
for(int x=0; x<60; x++)
{
System.out.println((Thread.currentThread()==this)+"..."+this.getName()+" run..."+x);
}
}
}
class ThreadTest
{
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<60; x++)
{
System.out.println("main....."+x);
}
}
}
/*
需求:多个窗口同时卖票。
*/
class Ticket implements Runnable//extends Thread
{
private int tick = 100;
public void run()
{
while(true)
{
if(tick>0)
{
System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
}
}
}
}
class TicketDemo
{
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();
}
}
多线程安全问题
原因:当多条语句操作同一个线程共享的数据时,一个线程中多条语句只执行了一部分,另一个线程进来参与运算,导致共享数据错误。
解决办法:对多条语句都操作共享数据时,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
Java对多线程安全问题提供了专业解决方法,就是同步代码块
synchronized(对象){需要被同步的代码}
class Ticket implements Runnable
{
private int tick = 1000;
Object obj = new Object();
public void run()
{
while(true)
{
synchronized(obj)
{
if(tick>0)
{
System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);
}
}
}
}
}
class TicketDemo2
{
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();
}
}
同步前提:
1、两个以上线程;
2、多个线程使用同一个锁。
保证同步中只能有一个线程进行
好处:解决了安全问题
弊端:判断锁消耗资源
/*
需求:
银行有一个金库。
有两个储户分别存300元,每次存100,存3次。
*/
class Bank
{
private int sum;
//Object obj = new Object();
public synchronized void add(int n)
{
//synchronized(obj)
//{
sum = sum + n;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println("sum="+sum);
//}
}
}
class Cus implements Runnable
{
private Bank b = new Bank();
public void run()
{
for(int x=0; x<3; x++)
{
b.add(100);
}
}
}
class BankDemo
{
public static void main(String[] args)
{
Cus c = new Cus();
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}
}
同步函数用的是哪一个锁?
函数需要被对象调用,那么函数都有一个所属对象调用就是this,所以同步函数的锁是this。
通过程序证明,一个线程在同步代码块中,一个线程在同步函数中,都在执行买票动作。
class Ticket 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);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....code : "+ tick--);
}
}
}
}
else
while(true)
show();
}
public synchronized void show()//this
{
if(tick>0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"....show.... : "+ tick--);
}
}
}
class ThisLockDemo
{
public static void main(String[] args)
{
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();
}
}
单例设计模式;
懒汉式与饿汉式的区别:懒汉式是对实例的延迟加载,在多线程操作时,懒汉式会出现安全隐患,用同步函数或加同步代码块可以解决安全隐患,但线程每次执行同步中的代码前都要先判断锁,会导致效率比较低,采用双重判断的方式可以解决效率问题。
package itcast;
//懒汉式
public class LanHanShi {
private LanHanShi(){}
private static LanHanShi lsh = null;
public static LanHanShi getInstance(){
if( lsh==null ){
synchronized(LanHanShi.class){
if(lsh==null)
lsh = new LanHanShi();
}
}
return lsh;
}
}
//饿汉式
class Single{
private Single(){}
private static final Single s = new Single();
public static Single getInstance(){
return s;
}
}
死锁:当同步中嵌套同步,而锁又不一样是,容易发生死锁。
package itcast;
public class DeadLock {
public static void main(String[] args) {
Thread t1 = new Thread(new Lock(true));
Thread t2 = new Thread(new Lock(false));
t1.start();
t2.start();
}
}
class Lock implements Runnable
{
private boolean flag;
Lock(boolean flag)
{
this.flag = flag;
}
Object obj1 = new Object();
Object obj2 = new Object();
public void run()
{
if(flag)
{
while(true)
{
synchronized(obj1)
{
System.out.println(Thread.currentThread().getName()+"...if locka ");
synchronized(obj2)
{
System.out.println(Thread.currentThread().getName()+"..if lockb");
}
}
}
}
else
{
while(true)
{
synchronized(obj2)
{
System.out.println(Thread.currentThread().getName()+"..else lockb");
synchronized(obj1)
{
System.out.println(Thread.currentThread().getName()+".....else locka");
}
}
}
}
}
}
线程间通讯:
其实就是多个线程在操作同一个资源,
但是操作的动作不同。
class Res
{
private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name,String sex)
{
if(flag)
try{this.wait();}catch(Exception e){}
this.name = name;
this.sex = sex;
flag = true;
this.notify();
}
public synchronized void out()
{
if(!flag)
try{this.wait();}catch(Exception e){}
System.out.println(name+"........"+sex);
flag = false;
this.notify();
}
}
class Input implements Runnable
{
private Res r ;
Input(Res 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 Output implements Runnable
{
private Res r ;
Output(Res r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
class InputOutputDemo2
{
public static void main(String[] args)
{
Res r = new Res();
new Thread(new Input(r)).start();
new Thread(new Output(r)).start();
}
}
生产者和消费者的实例:
import java.util.concurrent.locks.*;
class ProducerConsumerDemo2
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
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锁 进行获取。
该示例中,实现了本方只唤醒对方操作。
Lock:替代了Synchronized
lock
unlock
newCondition()
Condition:替代了Object wait notify notifyAll
await();
signal();
signalAll();
*/
class Resource
{
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 void set(String name)throws InterruptedException
{
lock.lock();
try
{
while(flag)
condition_pro.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
condition_con.signal();
}
finally
{
lock.unlock();//释放锁的动作一定要执行。
}
}
public void out()throws InterruptedException
{
lock.lock();
try
{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
condition_pro.signal();
}
finally
{
lock.unlock();
}
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.set("+商品+");
}
catch (InterruptedException e)
{
}
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.out();
}
catch (InterruptedException e)
{
}
}
}
}
import java.util.concurrent.locks.*;
class ProducerConsumerDemo2
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
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锁 进行获取。
该示例中,实现了本方只唤醒对方操作。
Lock:替代了Synchronized
lock
unlock
newCondition()
Condition:替代了Object wait notify notifyAll
await();
signal();
signalAll();
*/
class Resource
{
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 void set(String name)throws InterruptedException
{
lock.lock();
try
{
while(flag)
condition_pro.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
condition_con.signal();
}
finally
{
lock.unlock();//释放锁的动作一定要执行。
}
}
public void out()throws InterruptedException
{
lock.lock();
try
{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
condition_pro.signal();
}
finally
{
lock.unlock();
}
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.set("+商品+");
}
catch (InterruptedException e)
{
}
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.out();
}
catch (InterruptedException e)
{
}
}
}
}
/*
stop方法已经过时。
如何停止线程?
只有一种,run方法结束。
开启多线程运行,运行代码通常是循环结构。
只要控制住循环,就可以让run方法结束,也就是线程结束。
特殊情况:
当线程处于了冻结状态。
就不会读取到标记。那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态是,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。
Thread类提供该方法 interrupt();
*/
class StopThread implements Runnable
{
private boolean flag =true;
public void run()
{
while(flag)
{
System.out.println(Thread.currentThread().getName()+"....run");
}
}
public void changeFlag()
{
flag = false;
}
}
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)
{
t1.interrupt();
t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName()+"......."+num);
}
System.out.println("over");
}
}
/*
join:
当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。
join可以用来临时加入线程执行。
*/
class Demo implements Runnable
{
public void run()
{
for(int x=0; x<70; x++)
{
System.out.println(Thread.currentThread().toString()+"....."+x);
Thread.yield();
}
}
}
class JoinDemo
{
public static void main(String[] args) throws Exception
{
Demo d = new Demo();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t2.start();
t1.join();
for(int x=0; x<80; x++)
{
System.out.println("main....."+x);
}
System.out.println("over");
}
}
yield方法
暂停当前线程对象,并执行其他线程,临时释放执行权,达到平均运行效果。