java基础之线程

线程的创建方式:三种方式:

1.通过继承 thread,重写run方法,没有返回值的


/**
 * 1.通过继承Thread实现多线程
 */
public class Thread1 extends Thread {
    @Override
    public void run() {
        //业务逻辑
        System.out.println();
        String str = "通过继承Thread实现多线程";
        try {
            sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < str.length(); i++) {
            //Thread.currentThread()  获取当前线程对象
            System.out.print(this.getName() + "   " + str.charAt(i));

        }
    }
}
//调用
public static void main(String[] args) {
       
       for (int i = 0; i <10 ; i++) {
           Thread1 t = new Thread1();
           t.start();
       }

    }

2.通过实现 runnable 接口,实现run方法,没有返回值


/**
 * 2.通过实现  runnable 来创建多线程
 */
public class Thread2 implements Runnable {
    @Override
    public void run() {
        String str= "通过实现  runnable 来创建多线程";
        for (int i = 0; i <str.length() ; i++) {
            System.out.println(Thread.currentThread().getName()+"   "+str.charAt(i));
        }
    }
}

public static void main(String[] args) {
       
        //runable
       Thread2 t2= new Thread2();
       for (int i = 0; i <2 ; i++) {
           Thread thread = new Thread(t2);
           thread.start();
       }

    }

以上两种相对来说,实现相对简单 thread 和 runnable的区别 (实际上是基础和接口的区别)

3.callable<V> 实现call方法,有返回值的


import java.util.concurrent.Callable;

/**
 * Callable 有返回值的多线程
 */
public class Thread3 implements Callable<Integer> {
    private Integer num1;
    private Integer num2;

    public Thread3(Integer num1,Integer num2){
        this.num1=num1;
        this.num2=num2;
    }
    @Override
    public Integer call() throws Exception {
        return Math.max(num1, num2);
    }
}

//调用方法     
@Test
   public void test() throws Exception {
        Thread3 t =new Thread3(55, 111);
        FutureTask future = new FutureTask(t);
        Thread3 t2 =new Thread3(555, 101);
        FutureTask future2 = new FutureTask(t2);
       线程池
        ExecutorService es = Executors.newScheduledThreadPool(10);
        es.submit(future);
        es.submit(future2);
        es.shutdown();
        System.out.println(future.get());
        System.out.println(future2.get());
        System.exit(0);

    }

案例1:

时钟


/**
 * 时钟案例
 */
public class ThreadTimeDemo extends Thread {
    private SimpleDateFormat sdf ;
    public ThreadTimeDemo(String type){
        sdf = new SimpleDateFormat(type);
    }
    @Override
    public void run() {
        while (true) {
            System.out.println(sdf.format(new Date()));
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


public class ThreadDemo {

    public static void main(String[] args) {
       
       //时钟案例
       ThreadTimeDemo time = new ThreadTimeDemo("HH:mm:ss");
       time.start();
//interrupt 停止状态
       Thread1 t = new Thread1();
       t.start();
       t.interrupt();

    }

}

案例2:

火车站售票


/**
 * 线程中的具体逻辑:
 * 设置总票数  100
 * 买票,怎么卖?
    * 使用循环进行卖票,每卖出一张,打印被卖出票的信息,总票数执行--操作
 * <p>
 * 什么时候终止?
 * 如果>0才卖票,否则终止
 *
 * 出现并发问题,怎么解决?(票被重复卖出,多线程并发引起的问题)
 * 用同步锁进行解决,线程锁,所有线程持有同一把锁,按顺序执行,作用在出错的业务代码中
 * synchronized(线程锁对象){需要顺序处理的业务代码}
 */
public class Ticket extends Thread {
    private static int ticketCount = 30;
    private static Object obj = new Object();

    @Override
    public void run() {
        while (true) {
            if (ticketCount > 0) {
                try {
                    synchronized (obj) {
                        sleep(1);
                    }
                    System.out.println(this.getName() + "当前卖出的票号是:" + ticketCount--);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                System.exit(0);
            }
        }
    }
}


public class ThreadDemo {

    public static void main(String[] args) {
      
//卖票案例
           Ticket ticket = new Ticket();
           ticket.start();
       Ticket ticket1 = new Ticket();
       ticket1.start();
       Ticket ticket2 = new Ticket();
       ticket2.start();

    }

}

多线程下载案例

需求: 多线程下载功能 (网络下载 ) http://mirrors.cn99.com/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2009.iso

下载类


import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

/**
 * 多线程下载
 * @author wyl
 * 通过URL和下载资源建立联系
 * 设置参数,读取的范围
 * 开始进行文件的读取和写入
 * 关闭流
 *
 */
public class DownLoad2 extends Thread {
	//多线程下载需要的信息
	private long startIndex;
	private long endIndex;
	private int threadId;
	private String name;
	private static String path="D:\\upload\\";

	static {
		File file  = new File(path);
		if(!file.exists()){
			file.mkdirs();
		}
	}

	public DownLoad2(long startIndex, long endIndex, int threadId,String name) {
		this.startIndex = startIndex;
		this.endIndex = endIndex;
		this.threadId = threadId;
		this.name=name;
	}

	@Override
	public void run() {
		long start =System.currentTimeMillis();
		try {
			//统一资源管理器,可以直接打开网络地址
			URL url = new URL(DownLoadTest2.path);//获取资源地址
			//因为是基于Http请求,获取httpUrlConnection,获取网络连接对象,和服务器建立联系
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			//设置参数
			conn.setRequestMethod("GET");
			conn.setConnectTimeout(50000);//连接超时
			conn.setReadTimeout(100000);//读取超时
			conn.addRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);//设置读取范围
			
			if(conn.getResponseCode()==206) {//部分数据ok
				//取出连接中的数据
				InputStream is = conn.getInputStream();
				//提供一个接收的地方(本地接收)

				File file = new File(path+name);
				//输出流,开始写数据,随机读写流
				RandomAccessFile raf = new RandomAccessFile(file, "rwd");
				raf.seek(startIndex);//跳转到线程开始的位置
				System.out.println("线程:"+this.getName()+"  "+threadId+" 开始的位置:"+startIndex+"---"+" 结束位置"+endIndex);
		          
				int i=0;
				byte [] buf= new byte[8192];//字节数组,提高读取速度
				int len=0;//字节数组读取的长度
				while((len=is.read(buf))!=-1) {
					System.out.println(this.getName()+"  "+(i++));
					raf.write(buf, 0, len);
				}
				raf.close();
				is.close();
				
				DownLoadTest2.okThread++;
				
				synchronized (DownLoadTest2.path) {
					System.out.println("线程:"+this.getName()+threadId+"下载完毕...   "+DownLoadTest2.okThread);
					if(DownLoadTest2.okThread==DownLoadTest2.countThread) {
						DownLoadTest2.okThread=0;
					}
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		long end =System.currentTimeMillis();
		System.out.println("线程:"+this.getName()+threadId+"运行时间"+(end - start));
	}
}

下载测试类

/**
 * 多线程下载测试类
 */
public class DownLoadTest2 {
	
	static String path = "http://mirrors.cn99.com/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2009.iso";
	static int countThread=2;//线程数
	static int okThread=0;//和线程数有关,记录线程完成的个数
	public static String name = "CentOS-7-x86_64-DVD-2009.iso";
	
	public static void main(String[] args) throws Exception {
		long start =System.currentTimeMillis();
		//统一资源管理器,可以直接打开网络地址
		URL url = new URL(DownLoadTest2.path);
		//因为是基于Http请求,获取httpUrlConnection,获取网络连接对象,和服务器建立联系
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		//设置参数
		conn.setRequestMethod("GET");
		conn.setConnectTimeout(50000);//连接超时
		conn.setReadTimeout(200000);//读取超时
		//判断资源链接是否建立成功,成功进行多线程下载分配
		if(conn.getResponseCode()==200) {//成功
			//获取文件总长度
			long count = conn.getContentLengthLong();
			//每个线程下载的大小
			long size = count/countThread;
			//开启线程进行下载
			for (int i = 0; i < countThread; i++) {
				long startIndex=size*i;//开始位置     0  		102.4
				long endIndex=size*(i+1);//结束位置   102.4		204.8
				DownLoad2 thread = new DownLoad2(startIndex,endIndex , i,name);
				thread.start();
			}
		}
		long end =System.currentTimeMillis();
		System.out.println(end-start);
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自由自在1039

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值