您的位置:首页 > 编程语言 > Java开发

关于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的对象锁");

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: