1,多线程:进程是一个正在执行的程序,线程是进程中的一个独立的控制单元,线程控制着进程的执行,一个进程中至少有一个线程。
2,如何创建线程:
方法一:定义一个类继承Thread类,并覆写它的run()方法。
class ThreadDemo extends Thread{
public void run(){
//需要同步的代码。
}
public static void main(String[] args){
//每new一个新的Thread的子类对象,就创建了一个线程,当调用这个对象的start()方法时启动一个线程
new ThreadDemo().start();
for(int i=0;i<100;i++)
System.out.println("main is run");
}
}
方法二:自定义一个类实现Runnable接口,并覆写Runnable中的run方法,将此类的对象作为参数传入Thread的构造函数中,
然后通过Thread对象的start方法开启线程。
class Ticket implement Runnable{
public void run(){
//需要多线程运行的代码;
}
}
class TicketDemo{
public static void main(String[] args){
new Thread(new Ticket()).start();
new Thread(new Ticket()).start();
}
}
注意:多个线程都在获取cpu的执行权,在某一时刻cpu只能执行一个程序(多核除外)。
3,线程的常用方法:currentThread(); //返回当前正在执行的线程引用。
getName(); //返回该线程的名称。
getPriority(); //返回该线程的优先级。
interrupt(); //强制清除线程的中断状态,使其恢复到运行状态,抛出InterruptedException异常。
isAlive(); //测试线程是否处于活动状态。
join(); //等待该线程终止。当a线程执行到了b线程的join方法时,a线程要等b线程执行完后再继续执行。
setName(String s); //设置线程名称。
setDaemon(boolean on) //需要在线程开启之前设置,守护线程也叫后台线程,当所有前台线程都结束时后台线程自动结束。
setPriority(int i);//设置线程的优先级。也可以自定义(1-10之间的数)。
线程的三个优先级 :MAX_PRIORITY
MIN_PRIORITY
NORM_PRIORITY
sleep(long l); //让线程休眠long秒。是线程的冻结状态。
yield(); //暂停当前的线程对象,执行其他线程。
wait()¬ify; //等待唤醒线程,是线程的冻结状态,cpu放弃了执行资格。
stop(); //线程停止。还有一种情况就是run方法执行完成。
4,多线程运行时会出现安全问题,产生安全问题的原因:当多条语句操作同一个线程的共享数据时,一个线程只执行了多条语句的一部分,
没有全部执行完,而另个一线程抢到了执行权,对共享数据进行操作,造成共享数据错误。
解决办法:让一个线程把多条语句执行完,如果一个线程正在执行共享语句,没有执行完,其他线程不能操作共享语句。
java中提供了同步代码块synchronized(锁){要被同步的代码}
同步的前提:1,必须有两个以上的线程。
2,多个线程必须使用的是同一个锁。
5,synchronized关键字。
同步函数:public synchronized void show(){} //此函数用的同步锁是 this。
静态同步函数:publlic static synchronized void show(){} //此方法使用的同步锁是此静态函数所在的类的类名.class文件。
同步代码块的应用,单例设计模式。
懒汉式:class Single{
private static Single s = null; //先不new对象,调用时在new对象。
private Single(){}
public static Single getInstance(){
if(s==null){ //双重判断。
synichronized(Single.class){
if(s==null){
s = new Single();
}
}
}
return s;
}
}
6,死锁:在多线程中,当一个同步代码中嵌套另一个同步代码,而且两段代码持有的锁不一样,而且互相需要对方的锁时会发生死锁。
例如:class LockDemo implements Runnable{
public static Object locka = new Object();
public static Object lockb = new Object();
private boolean flag = true;
LockDmeo(boolean flag){
this.flag = flag;
}
public void run(){
if(flag){
while(true){
synchronized(locka){ //线程1进入拿到locka锁
System.out.println("111"); //执行到此处,执行权被线程2抢走。
synchronized(lockb){ //1线程抢回执行权,但是需要lockb锁,线程2没有释放lockb锁,所以形成死锁。
System.out.println("222");
}
}
}
}
else{
while(true){
synchronized(lockb){ //线程2拿到lockb锁,需要locka锁,而线程1没有释放locka锁。
System.out.println("333");
synchronized(locka){
System.out.println("444");
}
}
}
}
}
public static void main(String[] args){
new Thread(new LockDemo(true)).start();
new Thread(new LockDemo(false)).start();
}
}
7,Lock接口:1.5的新特性!可以支持多个相关的 Condition 对象。
lock()、unlock()方法替代了原来的synchronized().
通过lock.newCondition()获得一个Condition对象,Condition对象中的await()方法替换了wait()方法,signal()、signalAll()方法
替换了原来的notify()、notifyAll()方法.
可以通过创建多个Condition对象来指定要等待的对象和要唤醒的对象。
通过Lock对多线程进行同步的一个实例:
package lockday1;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Resource {
private String name;
public int count = 1;
private boolean flag = false;
final Lock lock = new ReentrantLock();
final Condition locka = lock.newCondition();
final Condition lockb = lock.newCondition();
public void set(String name){
lock.lock();
while(flag){
try {
locka.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.name = name + count;
count++;
System.out.println(Thread.currentThread().getName()+"生产者------------"+this.name);
flag = true;
lockb.signal();
lock.unlock();
}
public void get(){
lock.lock();
while(!flag){
try {
lockb.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"消费者----"+this.name);
flag = false;
locka.signal();
lock.unlock();
}
}
class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true)
if(r.count<1000){
r.set("汽车");
}
}
}
class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true)
if(r.count<1000){
r.get();
}
}
}
package lockday1;
public class LockTest1 {
public static void main(String[] args){
Resource r = new Resource();
new Thread(new Producer(r)).start();
new Thread(new Consumer(r)).start();
}
}