谈谈java线程锁synchronized关键字和volatile关键字
2014-01-24 11:08
746 查看
--记录蛋疼的那些日子--
最近和往常一样在群里聊天,一个哥们自己写了一个多线程下载程序,不知道他写来下片还是干吗,
遇到下载只能到99%的问题,但是呢下载下来的东西又能用,这让他头疼不已,
最后加了个synchronized(object){}搞定一切。
但是问题还在,刚好我闲来无事就查查资料学习学习。
-----------------------------------------群号183436336
先上代码
最近和往常一样在群里聊天,一个哥们自己写了一个多线程下载程序,不知道他写来下片还是干吗,
遇到下载只能到99%的问题,但是呢下载下来的东西又能用,这让他头疼不已,
最后加了个synchronized(object){}搞定一切。
但是问题还在,刚好我闲来无事就查查资料学习学习。
-----------------------------------------群号183436336
先上代码
import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.atomic.AtomicInteger; public class UpdateReceiver { private AtomicInteger length = new AtomicInteger(0); private RandomAccessFile accessFile; private int test = 0; private static Object object=new Object(); private Integer nInteger = new Integer(0); class ITest{ public Integer length = 0; public void setValue(int arg0){ length = length + arg0; } } private volatile ITest itest = new ITest(); private synchronized void setValue(int arg0,int threadId){ //test = arg; test = test + arg0; /** * 测试锁方法 */ /*if(threadId==0){ try { Thread.sleep(1000*10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }*/ } /** * * @param path 资源下载路径 * @param threadNum 线程数 * @param filepath 保存文件路径 */ public void download(String path, int threadNum,String filepath) { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(3000); conn.setRequestMethod("GET"); if (conn.getResponseCode() == 200) { int fileLength = conn.getContentLength(); // 获取网络资源文件大小,有些服务器不支持暂时不考虑 File file = new File(filepath); System.out.print(fileLength+"\n"); accessFile = new RandomAccessFile(file, "rwd"); accessFile.setLength(fileLength); // 设置保存文件的大小为获取到的大小 int block = fileLength % threadNum == 0 ? fileLength/ threadNum : (fileLength / threadNum) + 1; // 计算文件应该分为几块 System.out.println("block:"+block); for (int threadId = 0; threadId < threadNum; threadId++) { //新建线程开始下载 new DownloadThread(threadId, block, path, file).start(); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public class DownloadThread extends Thread { private int threadId; private int block; private String path; private File file; public DownloadThread(int threadId, int block, String path, File file) { this.threadId = threadId; this.block = block; this.path = path; this.file = file; } public void run() { super.run(); int start = threadId * block; // 文件单块开始写入的位置 int end = (threadId + 1) * block - 1; // 文件单块结束位置 InputStream in = null; RandomAccessFile accessFile = null; try { accessFile = new RandomAccessFile(file, "rwd"); accessFile.seek(start);//指定开始写入位置 URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(3000); conn.setRequestMethod("GET"); conn.setRequestProperty("Range", "bytes=" + start + "-" + end);// 设置从网络读取文件块位置 System.out.println("bytes=" + start + "-" + end); if (conn.getResponseCode() == 206) { in = conn.getInputStream(); byte[] buffer = new byte[1024*10]; int len = 0; while ((len = in.read(buffer)) != -1) { /** * 方法一:通过锁方法实现同步 * 当任意线程进入setValue()方法的时候,其它线程不得访问,需等待当前线程结束该方法 */ { accessFile.write(buffer,0, len); setValue(len,threadId); System.out.println(test*100/accessFile.length()+"%"); } /** * 方法二:AtomicInteger原子操作,额。。。。。也没有详细研究 */ /*{ accessFile.write(buffer,0, len); length.addAndGet(len); System.out.println(length.get()*100/accessFile.length()+"%"); }*/ /** * 方法三:加变量锁 * 当任意线程访问此块代码,其它线程需等待结束 */ /*synchronized(object){ accessFile.write(buffer,0, len); test = test + len; System.out.println(test*100/accessFile.length()+"%"); } */ /** * 错误方法,volatile修饰的变量只能内存地址是一样的,不能lock方法 */ /*{ accessFile.write(buffer,0, len); itest.set 4000 Value(len); System.out.println(itest.length*100/accessFile.length()+"%"); }*/ /** * 方法四:同样变量锁 */ /*synchronized(itest){ accessFile.write(buffer,0, len); itest.setValue(len); System.out.println(itest.length*100/accessFile.length()+"%"); }*/ /** * 错误 */ /*synchronized(nInteger){ accessFile.write(buffer,0, len); nInteger = nInteger + len;//每次又创建一个新对象 System.out.println(nInteger*100/accessFile.length()+"%"); }*/ } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { System.out.println("length:"+threadId+":"+length); System.out.println("test:"+threadId+":"+test); if (accessFile != null && in != null) { accessFile.close(); in.close(); } } catch (IOException e) { e.printStackTrace(); } } } } }
相关文章推荐
- java线程5 volatile和synchronized关键字 .
- Java线程入门学习5----volatile和synchronized关键字
- Java线程锁,以及volatile、synchronized、Lock关键字
- Java线程同步中关键字synchronized详述
- java 线程及synchronized关键字
- Java线程(二):线程同步synchronized和volatile
- Java线程同步中关键字synchronized详述
- 【Java并发系列04】线程锁synchronized和Lock和volatile和Condition
- Java线程中的volatile和synchronized的比较
- JAVA线程同步synchronized关键字及锁解析
- Java线程:volatile关键字
- Java多线程-通过线程的中断来深入学习interrupt方法,Volatile关键字
- Java线程的简单等待与唤醒【synchronized关键字】
- java多线程学习一线程安全之内存、synchronized、volatile
- Java 关键字volatile 和synchronized的作用
- java线程中volatile关键字的作用
- java线程同步:synchronized关键字,Lock接口以及可重入锁ReentrantLock
- Java 线程概述: 线程种类、状态,原子性、内存可见性、synchronized、volatile
- java线程总结--synchronized关键字,原理以及相关的锁
- Java线程:volatile关键字