java多线程例子学习笔记
java在2007年的时候编写过多线程爬虫,当时对多线程的理解仅仅限于可以同时并发任务,对于多线程之间的调度,完全没有理解。所以后来这的多线程的应用仅仅限于只能多线程并发任务。其实一切在线程中都可以被监控。
看下面的列子,我们来理解多线程之间如何进行控制的。
<table width="620" align="center" border="0" cellpadding="1" cellspacing="1" style="background:#FB7"> <tr> <td width="464" height="27" bgcolor="#FFE7CE"> 代码如下</td> <td width="109" align="center" bgcolor="#FFE7CE" style="cursor:pointer;" onclick="doCopy('copy4478')">复制代码</td> </tr> <tr> <td height="auto" colspan="2" valign="top" bgcolor="#FFFFFF" style="padding:10px;" class="copyclass" id=copy4478>package com.javaer.thread;
public class PrintABC {
public static Boolean isThreadA = true;
public static Boolean isThreadB = false;
public static Boolean isThreadC = false;
public static void main(String[] args) {
final PrintABC abc = new PrintABC();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i ) {
synchronized (abc) {
while (!isThreadA) {
try {
abc.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.print("A");
isThreadA = false;
isThreadB = true;
isThreadC = false;
abc.notifyAll();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i ) {
synchronized (abc) {
while (!isThreadB) {
try {
abc.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.print("B");
isThreadA = false;
isThreadB = false;
isThreadC = true;
abc.notifyAll();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i ) {
synchronized (abc) {
while (!isThreadC) {
try {
abc.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.print("C");
isThreadA = true;
isThreadB = false;
isThreadC = false;
abc.notifyAll();
}
}
}
}).start();
}
}
输出结果如下 :ABCABCABCABCABC
思路:解题思路大概是这样的,开启三个线程,每个线程一次打印一个字母,并且按照一定的顺序打印,当打印A的时候,其他线程处于阻塞状态,打印完A以后,将线程解锁,让打印B的那个线程开启,其他线程处于阻塞状态,同理打印C的时候,阻塞其他线程,这三个线程顺序循环,就达到顺序多次打印ABC的目的了。
这道题看似思路简单,其实主要需要用到wait()方法和notify()方法,还有关键字synchronized,只有充分理解了这些,才能解出这道题。下面我有必要讲解一下这两个方法,还有关键字synchronized。
多线程并行下载的核心特点就是分段,并行下载。
比如一个文件200M,分5个线程,那么就给砍成5份,分别同时下就好了。速度当然比一点点下载来的要快的多。
package com.javaer.examples.file;
import java.io.File;
import java.io.FileWriter;
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.net.URLConnection;
public class MyMutilDown {
/**
* 单线程的远程下载
*/
public void SingleDown(String filePath, String url) {
try {
// 要写入的文件
File file = new File(filePath getFileExtName(url));
FileWriter fWriter = new FileWriter(file);
URL ul = new URL(url);
URLConnection conn = ul.openConnection();
conn.setConnectTimeout(2000);// 请求超时时间
// int len = conn.getContentLength();
InputStream in = conn.getInputStream();
// byte[] by = new byte[1024];
int temp = 0;
while ((temp = in.read()) != -1) {
System.out.println(temp);
fWriter.write(temp);
}
fWriter.close();
in.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 文件后缀名
*
* @param path
* @return
*/
public String getFileExtName(String path) {
return path.substring(path.lastIndexOf("."));
}
/**
* 测试多线程
*
* @param filePath
* 文件保存路径
* @param url
* url
* @param tnum
* 线程数量
*/
public void MutiDown(String filePath, String url, int tnum) {
try {
// 要写入的文件
final File file = new File(filePath getFileExtName(url));
System.out.println(file.getAbsolutePath());
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");// 建立随机访问
final URL ul = new URL(url);
HttpURLConnection conn = (HttpURLConnection) ul.openConnection();
conn.setConnectTimeout(2000);// 请求超时时间
conn.setRequestMethod("GET");
int len = conn.getContentLength();// 文件长度
accessFile.setLength(len);
accessFile.close();
final int block = (len tnum - 1) / tnum;// 每个线程下载的快大小
for (int i = 0; i < tnum; i ) {
final int a = i;
new Thread(new Runnable() {
int start = block * a;// 开始位置
int end = block * (a 1) - 1;// 结束位置
@Override
public void run() {
HttpURLConnection conn2 = null;
RandomAccessFile accessFile2 = null;
InputStream in = null;
try {
conn2 = (HttpURLConnection) ul.openConnection();
conn2.setConnectTimeout(2000);// 请求超时时间
conn2.setRequestMethod("GET");
// TODO Auto-generated method stub
conn2.setRequestProperty("Range", "bytes=" start
"-" end "");// 设置一般请求属性 范围
in = conn2.getInputStream();
byte[] data = new byte[1024];
int len = 0;
accessFile2 = new RandomAccessFile(file, "rwd");
accessFile2.seek(start);
while ((len = in.read(data)) != -1) {
System.out.println(a "/" len);
accessFile2.write(data, 0, len);//并发写入
}
System.out.println("线程:" a "下载完成!");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
try {
accessFile2.close();
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
MyMutilDown mydown = new MyMutilDown();
String path = "http://www.jiaochengji.com/ openx-220080603.rar";
// mydown.SingleDown("/", path);
mydown.MutiDown("/bbc", path, 3);
}
}
注明:本文版权属于ITeye会员 lohasle
您可能感兴趣的文章:
java工作笔记之多线线程实例详解
java多线程例子学习笔记
java中字符串学习笔记
Java入门笔记1_HelloWorld
多线程程序设计 (转)
Java中java.lang.Void类学习笔记
Golang笔记:语法,并发思想,web开发,Go微服务相关
java多线程的优先级实例程序
初学Java注意什么?
java多线程休眠工作笔记