线程

java线程

进程与线程

进程

  • 进程就是内存中运行的程序
  • 并发:并发就是同一时间段cpu执行多个进程,执行完一个在执行下一个
  • 并行:并行就是同一时刻cpu执行多个进程

线程

线程是进程的一部分,是程序进入cpu的一条路径,一个进程中可以并发多个线程,每条线程并行执行不同的任务,多线程值得就是就是在同一时刻能够执行多个线程,单线程指的是同一时刻只能执行一个线程,线程示例如下:

  • 守护线程
    守护线程就是一类类似于垃圾回收机制的线程,因为进程会在所有线程结束后才消失,但是垃圾回收机制线程不会结束就会导致进程也不会结束,所以需要将它们标志了守护线程,Java 虚拟机会在所有非守护线程终止后结束进程。守护线程地创建如下:
Thread thread = new WatchingThread();
thread.setDaemon(true);
thread.start();

线程调度和线程状态

线程调度值的是cpu执行线程的实际情况,有以下两种:

  • 分时调度
    分时调度是线程轮流平均使用cpu,每个线程占用cpu时间相同
  • 抢占式调度
    抢占式调度是按照线程的优先级,来决定cpu先执行哪个进程,如果优先级相同则会随机选择,即线程随机性

线程状态
每个Java程序都有一个缺省的主线程,Application的主线程是main()方法的执行过程;Applet的主线程是通过浏览器加载并执行java小程序。Java使用Thread类及其子类表示线程5中状态:
新建(Newborn)->就绪(Runnable)->运行(Running)->阻塞(Blocked)->死亡(Dead)

线程实现

通过继承Thread类来创建并启动多线程:

  • 定义Thread类的子类并重载线程运行体run() 方法,run()方法中定义线程需要完成的任务。
  • 创建 Thread 子类的实例,即创建了线程对象。
  • 使用线程对象的 start() 方法来启动该线程。
    e.g.示例,该示例将会不停地输出两个线程地名字:
//继承Thread类重写run方法
package TreadTest;

public class MyThread extends Thread{
    @Override
    public void run() {
        while(true) System.out.println(currentThread().getName()+"运行");
    }
}
//创建多线程
package TreadTest;

public class TreadTets {
    public static void main(String[] args) {
        MyThread myThread1 = new MyThread();
        myThread1.setName("thread_1");
        MyThread myThread2 = new MyThread();
        myThread2.setName("thread_2");
        myThread1.start();
        myThread2.start();
    }
}

使用多线程复制文件

在Thread子类重写run方法,在其中定义复制文件即可

//创建Thread子类
package TreadTest;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class MyThread extends Thread {
    public MyThread(String source,String target){
        this.souce = source;
        this.target = target;
    }
    private String souce;
    private String target;

    @Override
    public void run() {
        try {
            FileInputStream fis = new FileInputStream(souce);
            FileOutputStream fos = new FileOutputStream(target);
            byte b[] = new byte[1024];
            int len;
            while ((len = fis.read()) != -1) {
                fos.write(b, 0, len);
            }
            fis.close();
            fos.close();
        }catch (IOException e){
            System.out.println("复制失败");
        }
    }
}



//创建多线程
package TreadTest;

public class CopyThreadTest {
    public static void main(String[] args) {
        for(int i=1;i<=3;i++){
            String source = "D:/javaTestFile/"+ i + ".txt";
            String target = "D:/javaTestFile/"+ i + "(" + i + ")" + ".txt";
            MyThread myThread = new MyThread(source,target);
            myThread.start();
        }
    }
}

结果如下,多线程创建成功

通过实现Runable接口实现多线程

这种方法与与继承Thread类差不多,编写一个类实现 Runnable 接口,并实现该接口中的 run() 方法。然后创建 Runable 实现类的实例,并以此实例作为 Thread 的 target 来创建 Thread 对象,示例如下:

//实现runable接口
package TreadTest;

public class MyThread_1 implements Runnable{
    public void run(){
        while(true){
            System.out.println("线程:"+ Thread.currentThread().getName()+"运行!");
        }
    }

}


//创建多线程
package TreadTest;

public class Test_1 {
    public static void main(String[] args) {
        MyThread_1 target = new MyThread_1();
        Thread thread1 = new Thread(target);
        thread1.setName("线程——1");
        Thread thread2 = new Thread(target);
        thread1.setName("线程——2");
        thread1.start();
        thread2.start();
    }
}

两种创建多线程方式比较

相比来说,实现Runanle接口更好:

  • 适合多个相同程序代码的线程去处理同一资源的情况,把线程同程序代码、数据分离较好地体现了面向对象的设计思想。
  • 可以避免由于 Java 的单继承特性带来的局限。
  • 有利于程序的健壮性,代码能够被多个线程共享。

同步synchronized

为了解决某些因为数据同步调用而产生地线程不安全问题,我们需要使用监视器实现线程同步,线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。监视器的原理如下::

Synchronized能够实现同步的原因是: - 当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例有关的锁。 - 当程序运行到synchronized同步方法或代码块时才该对象锁才起作用。 - 一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放,即该线程退出了synchronized同步方法或代码块。

Synchronized与static类似,Synchronized代码块和Synchronized方法作用相同,形式不同,作用范围不同:
e.g.示例如下:

//Synchronized代码块
package TreadTest;

public class TicketThread implements Runnable{
    private int count = 10;
    public void run(){
        while(true){
            synchronized (this){
                if (count > 0) {
                    try {Thread.sleep(1000);}
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()
                            +"窗口卖出了第"+count--+"张票");
                }
                else {
                    System.out.println("票已经售完了!");
                    break;
                }
            }
        }
    }
}

//Synchronized方法
package TreadTest;

public class TicketThread implements Runnable{
    private int count = 10;
    public synchronized void run(){
        while(true){
                if (count > 0) {
                    try {Thread.sleep(1000);}
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()
                            +"窗口卖出了第"+count--+"张票");
                }
                else {
                    System.out.println("票已经售完了!");
                    break;
                }
            }
    }
}

定时器

java提供了Timer计时器类,可以方便我们在指定时间执行任务,常用的用法如下:

  • timer.schedule(TimerTaskImpl tti,long ms) //延时ms毫秒执行任务
  • timer.schedule(TimerTaskImpl tti,long ms1,long ms2) //延时ms1毫秒后每隔ms2毫秒执行任务
  • timer.schedule(TimerTaskImpl tti,new Date(),long ms2) //每隔ms2毫秒后执行任务
    一般我们需要继承TimerTask并重写run方法,在通过Timer定时器调用,示例如下:
//继承TimerTask并重写run方法
package TreadTest;

import java.util.Timer;
import java.util.TimerTask;

public class TimeTask extends TimerTask{
     public void run(){}
}



//实现定时器
package TreadTest;

import java.util.Date;
import java.util.Timer;

public class TimeTest {
    public static void main(String[] args) {
        Timer timer = new Timer();
        //延时定时器
        timer.schedule(new TimeTask(){
            @Override
            public void run() {
                System.out.println("延时5s");;
            }
        },2000);
        //延时后定期执行定时器
        timer.schedule(new TimeTask(){
            @Override
            public void run() {
                System.out.println("一秒后执行任务,之后每隔一秒执行一次");
            }
        },2000,1000);
        //定期执行定时器
        timer.schedule(new TimeTask(){
            @Override
            public void run() {
                System.out.println("每隔3s执行一次");
            }
        },new Date(),3000);
    }
}

部分运行结果如下:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值