多线程--线程同步、死锁、守护线程、多线程下载

1 线程同步

当两个或多个线程需要访问同一资源时,需要确保该资源某一时刻只能被一个线程使用

1.1同步代码块

同步代码块:synchronized放在对象前面限制一段代码的执行

synchronized(对象)//这个对象可以为任意对象 

    需要被同步的代码 

同步条件
必须要有两个或者两个以上的线程 
必须是多个线程使用同一个锁 
缺点
多个线程需要判断锁,较为消耗资源

案例

class TicketRes implements Runnable {
	private int ticket = 10;// 票
	Object object=new Object();
	public void run() {
	// TODO Auto-generated method stub
	while (true) {
          synchronized(object){
	   if (ticket > 0) {
		System.out.println(Thread.currentThread().getName()
 		+ "--->卖"
		+ ticket--);
	    } else {
		break;
	    }
           }
         }
      }
   }

1.2同步方法

同步非静态方法:synchronized放在方法声明中,表示整个方法为同步方法,锁定this对象,如果有一个线程进入了该方法,其他线程要想使用当前this对象的任何同步方法,都必须等待前一个线程执行完该同步方法之后

同步static方法: synchronized放在static方法声明中,表示锁定该类的class对象(Xxx.class,是Class类型的,是描述一个类的信息的对象)
如果有一个线程进入了该方法,其他线程要想使用当前类中的任何同步静态方法,都必须等待前一个线程执行完该同步方法之后,其他非同步方法的执行不受影响.

public synchronized void method1(){
    …
}
public synchronized
static void method2(){
    …
}
public synchronized void method3(){
  …
}

1.3锁的选择

多个线程共享资源,为了保证数据安全,需要同步
一般情况下选择资源作为锁(必须为引用类型)即可,也可以选择其他唯一的对象

1.4同步代码块的应用

懒汉式单例模式

public class SingletonClass{
    private static SingletonClass instance=null;
    public static SingletonClass getInstance(){
        if(instance==null){//提高性能
            synchronized(SingletonClass.class){
                if(instance==null){
                    instance=new SingletonClass();
                }
            }
        }
        return instance;
    }
    private SingletonClass(){}
}

2 死锁

所谓死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

2.1死锁案例

public void run() {
if (flag) {
	synchronized (MyLock.locka) {
		System.out.println("if locka");
		synchronized (MyLock.lockb) {
			System.out.println("if lockb");
		}
	}
} else {
		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();
}
3 守护线程

在Java中有两类线程:
User Thread(用户线程或前台线程)  
Daemon Thread(守护线程或后台线程)
其实User Thread线程和Daemon Thread守护线程本质上来说去没啥区别的,唯一的区别之处就在虚拟机的离开:如果User Thread全部撤离,那么Daemon Thread也就没啥线程好服务的了,所以虚拟机也就退出了。

案例

public class DreamThreadDemo {
	public static void main(String[] args) {
		//创建线程对象
		DreamThread dt = new DreamThread();
		dt.setDaemon(true);
		dt.start();
		for (int i = 0; i < 50; i++) {
			System.out.println("主线程=============="+i);
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

class DreamThread extends Thread{
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 100; i++) {
			System.out.println("子线程=============="+i);
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
}

4 利用RandomAccessFile实现文件的多线程下载,即多线程下载一个文件时, 将文件分成几块,每块用不同的线程进行下载((模拟复制实现)

public class DownLoadFile {
	public static void main(String[] args) {
		File file = new File("d:\\11.jpg");
		long fileLen = 0;
		if (file.exists()) {
			fileLen = file.length();
		}
		
		int sublen = (int) (fileLen%4==0?fileLen/4:fileLen/4+1);
		DownLoadThread d1 = new DownLoadThread(0, sublen);
		DownLoadThread d2 = new DownLoadThread(sublen, sublen);
		DownLoadThread d3 = new DownLoadThread(sublen*2, sublen);
		DownLoadThread d4 = new DownLoadThread(sublen*3, (int)fileLen-sublen*3);
		
		d1.start();
		d2.start();
		d3.start();
		d4.start();
		
		
		
	}
}

class DownLoadThread extends Thread{
	private int skipCount;//要跳过的字节数
	private int len;//下载的长度
	public DownLoadThread(int skipCount, int len) {
		super();
		this.skipCount = skipCount;
		this.len = len;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		RandomAccessFile read =null;
		RandomAccessFile write = null;
		
		try {
			System.out.println(Thread.currentThread().getName()+"开始下载");
			read = new RandomAccessFile("d:\\11.jpg","rw");
			write = new RandomAccessFile("d:\\22.jpg", "rw");
			read.seek(skipCount);
			write.seek(skipCount);
			byte[] buff = new byte[len];
			read.read(buff);
			write.write(buff);
			System.out.println(Thread.currentThread().getName()+"下载完成");
			
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				if (read!=null) {
					read.close();
				}
				if (write!=null) {
					write.close();
				}
			} catch (Exception e2) {
				// TODO: handle exception
			}
			
		}
	}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值