关于java基础--线程的详解与测试
2015-07-22 21:34
246 查看
一、线程
1,线程
1-1,,继承Thread
* 线程的五个状态:新建,就绪(可运行状态),运行,阻塞(等待,挂起),消失方法:(1),继承thread类
(2),重写run()方法
(3),创建类调用start()方法
public class Thread01 extends Thread {
//线程的方法体
@Override
public void run() {
for(int i =0;i<10;i++){
System.out.println(this.getName()+"启动"+i);
}
}
public static void main(String[] args) {
//创建一个线程
Thread01 tt = new Thread01();
//不能直接调用run()方法,要不然就相当于一个方法体
//tt.run();
//为线程指定名字
tt.setName("子线程一");
//使当前线程处于可运行状态
tt.start();
Thread01 tt0 = new Thread01();
tt0.setName("子线程二");
tt0.start();
for(int i =0;i<10;i++){
//获取main方法的线程名
System.out.println(Thread.currentThread().getName()+"***"+i);
}
}
1-2,实现接口Runnable
方法:(1),实现接口Runnable(2),重写接口的方法run()
(3)创建类对象TestRannable tt = new TestRannable();
Thread t = new Thread(tt);
(4),调用start()进行线程排队
public class TestRannable implements Runnable {
@Override
public void run() {
for(int i =0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}
public static void main(String[] args) {
//创建当前类的对象
TestRannable tt = new TestRannable();
//创建一当前类为对象的线程,当前类为执行对象目标
Thread t = new Thread(tt);
//给线程设置名字
t.setName("线程1");
//让线程处于就绪状态
t.start();
TestRannable tt1 = new TestRannable();
//创建一当前类为对象的线程,当前类为执行对象目标
Thread t1 = new Thread(tt1);
//给线程设置名字
t1.setName("线程2");
//让线程处于就绪状态
t1.start();
for(int i =0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"--"+i);
}
}
1-3,join()加入另一个线程
* join()让指定的线程加入到当前的线程中来* 在被加入的线程执行完毕后,当前的线程才会执行
static B b = new B();
@Override
public void run() {
for(int i = 0;i<10;i++){
//当 i=5 的时候,把 b 线程假如到当前线程中
if(i==5){
try {
b.join();
System.out.println(this.getName()+"********"+i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
System.out.println(this.getName()+"********"+i);
}
}
2,用线程拷贝某个文件夹内.txt文件
步骤: (1),创建一个类继承Thread类(2),创建类成员:目标文件,目的文件
(3),重写方法体run()实现在其内进行文件的复制
(4)创建主函数main()
(5)运用接口FilenameFilter()匿名内部类实现文件格式的筛放入链表中
(6)遍历复制筛选的文件
public class TestCopyThread extends Thread{
File src = null;//定义一个目标文件
File dir = null;//定义一个目的文件
public TestCopyThread(File src,File dir){
this.src = src;
this.dir = dir;
}
@Override
public void run() {
BufferedReader fis = null;
BufferedWriter fos = null;
try {
fis = new BufferedReader(new FileReader(src));
fos = new BufferedWriter(new FileWriter(new File(dir,src.getName())));
//定义一个字字节数组
//byte[] b = new byte[fis.available()];
String s = null;
while((s= fis.readLine())!=null){
fos.write(s);
fos.newLine();
fos.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
//关闭资源
fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//源文件
File src = new File("e:"+File.separator+"c");
//目的文件
File dir = new File("e:"+File.separator+"d");
//过滤指定后缀为txt的文件
File[] files = src.listFiles(new FilenameFilter() {
//匿名内部类(文件过滤器)
@Override
public boolean accept(File dir, String name) {
if(name.endsWith(".txt")){
return true;
}
return false;
}
});
for(File f :files){
TestCopyThread tct = new TestCopyThread(f, dir);
tct.start();
}
}
}
3,文件监听
/** 创建一个线程去监听一个文件是否被修改
*/
步骤:(1)创建一个类继承Thread
(2)实现方法体run()
(3)捕获当前文件最后一次修改的时间last
(4)让线程休眠3秒钟然后重新捕获该文最后一次修改的时间newtime
(5)比较last与newtime是否相等
(6)若不相等格式化newtime为指定的时间格式并输出修改的时间
(7)若相等重复循环步骤4-5
public class FileListener extends Thread{
File file = null;
public FileListener(){}
public FileListener(File file){
this.file = file;
}
@Override
public void run() {
//获取当前文件最后被修改的时间
long last = file.lastModified();
while(true){
try {
//让线程休眠3秒钟
sleep(3000);
long newtime = file.lastModified();
if(last!=newtime){
System.out.println(file+" 文件被修改");
//修改时间显示的格式
SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//创建一个date对象,表示的时间为文件最后一次修改的时间
Date d = new Date(newtime);
String str = simple.format(d);
System.out.println("文件被修改的时间为:"+str);
last=newtime;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
File file = new File("e:"+File.separator+"a.txt");
FileListener t = new FileListener(file);
t.start();
}
}
4,在指定时间进行文件的备份
/*
* 在指定的时间自动备份文件
*/
步骤:(1)创建一个类继承Thread
(2)实现方法体run()
(3)创建指定备份的时间字符串ctime
(4)创建格式化时间的SimpleDateFormat变量
(5)监听当前的系统时间并格式化成指定格式的字符串ntime
(6)比较ctime与ntime是否相等
(7)若相等调用文件复制的方法copyFile()
(8)若不相等重复循环步骤5
(9)创建文件的复制方法体copyFile()
public class AutoCopyFile extends Thread{
//要备份的文件
File file = null;
File dir = null;
public AutoCopyFile(){}
public AutoCopyFile(File file,File dir){
this.file = file;
this.dir = dir;
}
@Override
public void run() {
//指定在11点整备份指定的文件
String ctime = "11:17";
//格式化当前的时间
SimpleDateFormat simple = new SimpleDateFormat("HH:mm");
//监听代码
while(true){
//格式化当前的时间
String ntime = simple.format(new Date());
//判断是否到了文件备份的时间
if(ctime.equalsIgnoreCase(ntime)){
//文件复制的方法
copyFile(file,dir);
}else{
try {
//让线程休眠3秒
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//文件复制的方法
public void copyFile(File file,File dir){
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(file);
fos = new FileOutputStream(new File(dir,file.getName()));
int len =0;
while((len = fis.read())!=-1){
fos.write(len);
fos.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
//关闭资源
fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
File file = new File("e:"+File.separator+"a.txt");
File dir = new File("e:"+File.separator+"c");
new AutoCopyFile(file,dir).start();
}
}
二、线程的方法
1,线程方法体yield()
* yield:是静态的方法.直接使用Thread.yield()调用* 作用:让当前正在执行的线程暂停执行,并且让自己处于就绪状态
* 所以说一个线程调用yield()方法时候,下一个有可能运行的还是它本身
Thread.yield();
2,线程安全修饰符synchronized
* 线程安全的,只允许一个一个的去调用synchronized* 只对加synchronized关键字的方法有用
public synchronized void run() {
代码块
}
3,模拟线程安全的售票
* wait():让当前线程等待,并且释放该线程的对象锁.方法中可以传一个long类型的数据,该参数指让该线程等待多少时间* synchronized:修饰线程同步,它可以修饰方法,也可以修饰代码块,也可以修饰类
* 不同的对象具有不同的对象锁,如果两个线程访问的不是同一个对象中的用synchronized关键字修饰的方法或代码块
* 它们之间不会相互排斥的
* synchronized修饰代码块时一定要在后面指定该同步关键字要同步打的那个对象,不能同步不同的数据类型
public class Testpiao implements Runnable{
static int num = 20;
@Override
public synchronized void run() {
while(num!=0){
if(num!=0){
--num;
System.out.println(Thread.currentThread().getName()+"售出一张票,目前"+"还剩余: "+num+"张票");
try {
Thread.sleep(1000);
notifyAll();//全部唤醒等待状态
this.wait(100);//等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if(num==0){
System.out.println("武汉到南昌的车票已经售完.....");
System.exit(0);
}
}
public static void main(String[] args) {
Testpiao tp = new Testpiao();
Thread[] ti =new Thread[5];
for(int i = 0;i<5;i++){
ti[i] = new Thread(tp);
ti[i].setName("售票员"+i);
}
for(int j = 0;j<5;j++){
ti[j].start();
}
}
}
4,验证守护线程
* 守护线程(后台线程):就是专门为用户线程服务.当一个程序中所有的用户* 线程都结束事,那么后台线程就会自动消失
* 用户手动创建的线程默认就是用户线程(main是一个主线程)
* 把一个用户线程设置为守护线程:setDaemon()
* 守护线程在监测到当前的程序没有用户线程存在时就会退出,但是在退出的时候会占用一定的时间
* 最简单的就是垃圾回收机制
//设置守护线程(也就是后台线程)
//t1.setDaemon(true);
public class TestDemon extends Thread{
@Override
public void run() {
try {
sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=0;i<10;i++){
System.out.println(this.getName()+"----"+i);
}
}
public static void main(String[] args) {
TestDemon t = new TestDemon();
//设置守护线程
t.setDaemon(true);
t.start();
for(int i=0;i<15;i++){
System.out.println(Thread.currentThread().getName()+"----"+i);
}
}
}
5,模拟线程死锁
String s1 = new String("s1对象锁");String s2 = new String("s2对象锁");
@Override
public void run() {
//通过线程ID来判断是第几个线程执行
if(Thread.currentThread().getId()==8){
System.out.println("第一个线程执行.........");
//获取s1的对象锁
synchronized (this.s1){
try {
//让当前线程休眠一秒
Thread.sleep(1000);
//s1.wait(100);打破Lock
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"休眠醒来...");
synchronized (this.s2){
System.out.println("线程一想要获取s2的对象锁");
}
}
}
if(Thread.currentThread().getId()==9){
System.out.println("第二个线程执行.........");
synchronized (this.s2){
try {
//休眠
Thread.sleep(1000);
//s2.wait(10);打破
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"线程二休眠醒来...");
synchronized (this.s1){
System.out.println("线程二想要获取s1的对象锁");
}
}
}
相关文章推荐
- Java框架篇---Mybatis 入门
- 关于java基础--PIO操作xls文件、持久化对象以及拷贝文件
- 算法学习之java实现希尔排序
- 关于java基础--IO流
- 深入理解JAVA虚拟机笔记 - 03
- java统计一个字符串中中文,英文,数字的个数
- 关于java基础--File类与FileFilter过滤器的详解与测试
- Spring(二)编码剖析Spring对JavaBean的管理
- Eclipse快捷键大全
- 关于java基础--日期类与日历类Calendar详解测试
- java常见几种排序
- java之设计模式---模板设计模式
- eclipse 启动后,啥也不干,就一直在loading descriptor for XXX (XXX为工程名),,其他什么操作都不能操作。 如下图所示,保存文件也无法保存。 这个怎么办?一年好几天,什么都干不了!!!!!
- Java线程(十一):Fork/Join-Java并行计算框架
- 算法学习之java实现插入排序
- eclipse php 开发环境搭建记录
- 关于Spring中MongoTemplate排序问题
- java迭代器
- Java集合框架
- Java对象生命周期