java多线程例子学习笔记

java在2007年的时候编写过多线程爬虫,当时对多线程的理解仅仅限于可以同时并发任务,对于多线程之间的调度,完全没有理解。所以后来这的多线程的应用仅仅限于只能多线程并发任务。其实一切在线程中都可以被监控。

看下面的列子,我们来理解多线程之间如何进行控制的。

 代码如下 复制代码

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.111cn.net/ openx-220080603.rar";
// mydown.SingleDown("/", path);
mydown.MutiDown("/bbc", path, 3);
}
}

注明:本文版权属于ITeye会员 lohasle

时间: 2024-09-26 03:44:02

java多线程例子学习笔记的相关文章

Java中jqGrid 学习笔记整理——进阶篇(二)_java

相关阅读: Java中jqGrid 学习笔记整理--进阶篇(一) 本篇开始正式与后台(java语言)进行数据交互,使用的平台为 JDK:java 1.8.0_71 myEclisp 2015 Stable 2.0 Apache Tomcat-8.0.30 Mysql 5.7 Navicat for mysql 11.2.5(mysql数据库管理工具) 一.数据库部分 1.创建数据库 使用Navicat for mysql创建数据库(使用其他工具或直接使用命令行暂不介绍) 2. 2.创建表 双击打

java泛型的学习笔记[2]—实际使用

继上一文<java泛型的学习笔记[1]-基础知识>之后,本文将介绍泛型的一些应用和应用过程中遇到的问题. 在此之前,我们先给出一张类图:   1)泛型类型的子类型问题 我们首先来看这样一句代码.该行代码正确,因为Cat是Animal的子类型 Animal animal=new Cat();// 但是再看下一句代码: AarrayList<Animal> animals=new ArrayList<Cat>();//编译出错        这句代码编译出错,因为虽然因为C

java对象序列化学习笔记

java对象|笔记 目前网络上关于对象序列化的文章不少,但是我发现详细叙述用法和原理的文章太少.本人把自己经过经验总结和实际运用中的体会写成的学习笔记贡献给大家.希望能为整个java社区的繁荣做一点事情.    序列化的过程就是对象写入字节流和从字节流中读取对象.将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,管道到另一线程中或通过网络连接将对象数据发送到另一主机.对象序列化功能非常简单.强大,在RMI.Socket.JMS.EJB都有应用.对象序列化问题在网

Java NIO 完全学习笔记(转)

本篇博客依照 Java NIO Tutorial 翻译,算是学习 Java NIO 的一个读书笔记.建议大家可以去阅读原文,相信你肯定会受益良多. 1. Java NIO Tutorial Java NIO,被称为新 IO(New IO),是 Java 1.4 引入的,用来替代 IO API的. Java NIO:Channels and Buffers 标准的 Java IO API ,你操作的对象是字节流(byte stream)或者字符流(character stream),而 NIO,你

java.util包学习笔记一

笔记 学习java2SDK 1.4.0 java.util里边有几个重要的接口,列在这里作为学习的总结: 1 java.util.Enumeration有两个方法hasMoreElements(),nextElement().使用方法如下://打印向量v的所有元素for(Enumeratin e = v.elements(); e.hasMoreElements();){ System.out.println(e.nextElement().toString());}这里注意要调用nextEle

Java软件开发学习笔记(一)

笔记 1. Java是一种现代的程序设计语言,并且生逢其时 Java语言拥有良好的特性(面向对象)和最好的价格(免费), 在最恰当的地方(在web上),又在最合适的时间(正好在web逐渐流行时)出现. 2. 1995年5月,第一版 1998年底,J2SDK 3. 抽象是计算中的关键概念 面向对象的程序设计集中于对抽象的识别和运用上 抽象是建立在分层上的 底层是编程语言,其上层是标准类库中的抽象,最上边的一层或若干层是由程序员建立的各种抽象 (每一层抽象都对实现为程序的系统提供一个较高层次的视角)

《深入理解Java虚拟机》学习笔记

自动内存管理机制 第2章 垃圾收集器与内存分配策略 1.Java虚拟机在执行java程序时会把它所管理的内存会分为若干个不同的数据区域, 这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在, 有些区域则是在以来用户线程的启动和结束而建立和销毁. 根据<Java虚拟机规范>,包括以下几个运行时数据区域: //此处应有类图,但是画起来太麻烦! 程序计数器(Program Counter Register) 方法区(Method Area) 虚拟机栈(VM Stack)

Java多线程CyclicBarrier学习

CyclicBarrier是多线程并发控制实用工具   CyclicBarrier初始化时规定一个数目,然后调用await()方法进入等待的线程数.当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续执行. await() 方法没被调用一次,计数便会减少1,并阻塞住当前线程.当计数减至0时,阻塞解除,所有在此 CyclicBarrier 上面阻塞的线程开始运行. CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍. CyclicBa

一位Java初学者的学习笔记

怎么样?是不是想起了自己当年挑灯苦学的场景,想起了当年被这些程序编码烦恼的日子?想变的牛逼就要多写代码,如果你想学习Java可以来这个群,首先是五三二,中间是二五九,最后是九五二,里面有大量的学习资料下载. 这些都是最基本的Java笔记,相信大家都是一看就会.