当前位置:  编程技术>移动开发
本页文章导读:
    ▪Java学习 之 多线程上载文件【源码】        Java学习 之 多线程下载文件【源码】 负责下载的线程: import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; public class DownloadThread extends Thread { // 定义字节.........
    ▪ 聚合框架        集合框架 数据多了用对象存储。对象多了用集合存储。 集合和数组的区别: 数据用于存储统一类型的数据,有固定的长度。 集合可以存储不同类型的数据,没有固定的大小。   结合的结构.........
    ▪ 多线程(2)       多线程(二) 自己设计多线程程序      如何设计使用线程呢?思考:线程是运行在进程上的,要使用线程必须先需要进程。进程是由windows系统分配给应用程序的。所以只要我们写的程序.........

[1]Java学习 之 多线程上载文件【源码】
    来源: 互联网  发布时间: 2014-02-18
Java学习 之 多线程下载文件【源码】

负责下载的线程:

import java.io.IOException;  
import java.io.InputStream;  
import java.io.RandomAccessFile;  
  
  
public class DownloadThread extends Thread {  
      
    // 定义字节数组(用于取水的那个竹筒)的长度  
    private final int BUFF_LEN = 100;  
    // 定义下载的起始点  
    private long start;  
    // 定义下载的结束点  
    private long end;  
    // 下载资源对应的输入流  
    private InputStream inputStream;  
    // 下载资源对应的输出流  
    private RandomAccessFile randomAccessFile;  
      
    // 构造器:传入起始下载点,结束下载点,输入流,输出流  
    public DownloadThread (long start,long end,InputStream inputStream,RandomAccessFile randomAccessFile) {  
        // 打印一下该线程的起始下载点和结束下载点的位置信息  
        System.out.println(start+" >------> "+end);  
        this.start = start;  
        this.end = end;  
        this.inputStream = inputStream;  
        this.randomAccessFile = randomAccessFile;  
    }  
      
    @Override  
    public void run() {  
        try {  
            // 记录指针向前移动start个字符  
            inputStream.skip(start);  
            // 记录指针定位到start位置处  
            randomAccessFile.seek(start);  
            // 定义读取输入流内容的缓存数组(竹筒)  
            byte[] buff = new byte[BUFF_LEN];  
            // 本线程负责下载的资源大小  
            long contentLen = end - start;  
            // 定义最多需要几次就可以完成本线程的下载任务,方便控制线程的退出  
            long readMaxTimes = contentLen/BUFF_LEN + 4;  
            // 实际读取的字节数  
            int reallyReadCount = 0;  
            for (int i = 0; i < readMaxTimes; i++) {  
                // 读取数据  
                reallyReadCount = inputStream.read(buff);  
                // 如果读取的字节数小于0,说明读取完毕,则退出循环  
                if (reallyReadCount < 0) {  
                    break;  
                }  
                // 写入数据  
                randomAccessFile.write(buff, 0, reallyReadCount);  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            // 使用finally块来关闭当前线程的输入流和输出流      
            try {  
                if (inputStream != null) {  
                    inputStream.close();  
                }  
                if (randomAccessFile != null) {  
                    randomAccessFile.close();  
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
          
}  

 

传入Url地址,开启下载:

import java.io.IOException;  
import java.io.InputStream;  
import java.io.RandomAccessFile;  
import java.net.MalformedURLException;  
import java.net.URL;  
import java.net.URLConnection;  
  
public class MultiDownload {  
      
    public static void main(String[] args) {  
        // 定义开启的线程数  
        final int DOWNLOAD_THREAD_NUM = 4;  
        // 定义下载文件的文件名,包括后缀  
        final String OUTPUT_FILE_NAME = "baidu.gif";  
        // 定义一个DOWNLOAD_THREAD_NUM大小的输入流数组  
        InputStream[] inArrays = new InputStream[DOWNLOAD_THREAD_NUM];  
        // 定义一个DOWNLOAD_THREAD_NUM大小的输出流数组  
        RandomAccessFile[] outArrays = new RandomAccessFile[DOWNLOAD_THREAD_NUM];  
          
        try {  
            // 创建一个URL对象,参数是我们要下载的资源的地址  
            URL downloadUrl = new URL("/img/baidu_sylogo1.gif");  
            // 以该URL对象打开第一个输入流  
            inArrays[0] = downloadUrl.openStream();  
            // 获取该网络资源文件的长度  
            long fileLength = getFileLength(downloadUrl);  
            // 做一个打印  
            System.out.println("该网络资源文件的大小:"+fileLength);  
            // 以输出的文件名创建第一个输出流对象,模式是可读,可写  
            outArrays[0] = new RandomAccessFile(OUTPUT_FILE_NAME, "rw");  
            // 创建一个与下载资源文件相同大小的空文件  
            for (int i = 0; i < fileLength; i++) {  
                outArrays[0].write(0);  
            }  
            // 计算每个线程应该下载的字节数  
            long everyThreadDownloadSize = fileLength/DOWNLOAD_THREAD_NUM;  
            // 计算整个下载资源整除后剩下的余数  
            long otherDownloadSize = fileLength%DOWNLOAD_THREAD_NUM;  
            // 启动各个线程下载各自规定的读取长度的资源  
            for (int i = 0; i < DOWNLOAD_THREAD_NUM; i++) {  
                // 刚才只初始化了第一个输入流和输出流对象,初始化剩下的输入流和输出流对象  
                if (i != 0) {  
                    inArrays[i] = downloadUrl.openStream();  
                    outArrays[i] = new RandomAccessFile(OUTPUT_FILE_NAME, "rw");  
                }  
                // 独立配置最后一个线程的下载参数(该线程负责下载整除后余下的资源)  
                if (i == DOWNLOAD_THREAD_NUM -1) {  
                    new DownloadThread(i*everyThreadDownloadSize, (i+1)*everyThreadDownloadSize+otherDownloadSize, inArrays[i], outArrays[i]);  
                } else {  
                    // 配置前几个线程的下载参数  
                    new DownloadThread(i*everyThreadDownloadSize, (i+1)*everyThreadDownloadSize, inArrays[i], outArrays[i]);  
                }  
            }  
        } catch (MalformedURLException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
          
          
    }  
      
    // 根据URL获取该URL所指向的资源文件的长度  
    private static long getFileLength(URL url) throws IOException{  
        long length = 0;  
        URLConnection urlConnection = url.openConnection();  
        long size = urlConnection.getContentLength();  
        length = size;  
        return length;  
    }  
}  

 

转自:http://emmet1988.iteye.com/blog/1065251


    
[2] 聚合框架
    来源: 互联网  发布时间: 2014-02-18
集合框架

数据多了用对象存储。对象多了用集合存储。

集合和数组的区别:

数据用于存储统一类型的数据,有固定的长度。

集合可以存储不同类型的数据,没有固定的大小。

 

结合的结构 :

                        collection

                               |

                               |

                   ——————————

                   |                            |

                   list                         set

            -------------            -----------------

            |        |      |                       |                |

    arraylist   vector  linkedlist      hashSet     Tree Set

 

********************************************

collection中的常用方法

add     clear  reomoveAll   retainALL (取交集) contains()  

做实验测试类可以用实现了Collection接口的arraylist测试。

 

注意:在集合中存对象,存的都是对象的地址。而不是直接把对象实体存入集合中。

 

**************************************************

Iterator i = arrayList.iterator();

while (i.hasNext()){

 

         system.out.println(i.next());

}

 

 

for(Iterator i =arrayList.iterator;i.hasNext();){

 

     systemt.out.println(i.next());

};

 

下面的for循环相对while来说效率高些。因为i是for内部的局部变量。

 

********************************************************

list 和set方法的区别

list 有索引,可以存储相同的元素

set 没有索引,不能存储相同的元素

 

 

 

list特有的方法

增  add(index ,collection) 删 remove(index)  改 set(index,collection)

查   get(index)  subList(int i,int to) 包含头不包含尾  listIterator

用迭代起操作查询集合,对集合的操作只能用迭代起的方法,而不能用集合的方法。

list迭代中特有的方法 listIterator 方法用其方法操作集合。


    
[3] 多线程(2)
    来源: 互联网  发布时间: 2014-02-18
多线程(二)

自己设计多线程程序

     如何设计使用线程呢?思考:线程是运行在进程上的,要使用线程必须先需要进程。进程是由windows系统分配给应用程序的。所以只要我们写的程序有入口,都是应用程序。通过查看api实现多线程有两种方法,现在我们首先了解第一种实现多线程的方法。

     继承Thread类并实现run方法,就可以实现多线程。

     怎么样启动一个线程呢?

    线程的启动需要手动的调用线程对象的start方法进程开启线程。

   开启线程的start方法中有两个作用1.启动线程  2.执行run方法

   线程的运行和进程一样。通常我们说所的线程之间会抢夺cpu资源,同过观察运行例子程序确实是这样的,但是实际上是分给cpu进程的cpu根据线程执行的优先权进程执行线程的。同一个时间,只有一个线程运行,不能多个线程并发的运行。

   我们写一个java应用,通过main入口的就是主线程,在主线程中我们可以开启子线程。主线程和子线程是快速交替的在进程中运行的。

 

病毒类的程序:一直抢先执行自己的线程,不允许其他程序抢占cpu资源。这个是病毒程序的设计的思路。

 

思考:为什么我们要覆盖run方法呢

         因为我们要在run方法中书写我们要执行的程序。父类thread 的run方法中为空的方法。

思考: Thread t  = new Thread(); t.star(); 这样能否开启线程

        这样能开启线程,同过start启动线程和执行线程的run方法是空的,这样的线程毫无意义

思考:我们用继承了线程的对象  t  直接调用run方法和start方法有什么却别

        直接调用t.run 方法,对我们来说跟调用普通方法的run方法是一样的,并没有执行线程。当一个程序执行到t.run方法的时候,只有执行完run方法才会执行下面的程序,这个执行是在主线程中,不会和主线程交替执行。调用run方法开启了线程。就会和主线程进行交替的执行。

 

 

线程的状态:

临时状态

 

     临时状态是有执行权,但是cpu暂时没有分配其执行。需要等待某个时刻由cpu分配了执行全,此线程就可以执行。

 

冻结状态:

      当线程调用sleep或wait方法的时候,线程主动放弃执行权。这时线程处于冻结状态。通知并告诉cpu这段时间不执行任何操作,所以cpu不会给其分配执行权。

     sleep 是睡眠多少秒后自动醒来,不需要别人叫醒。

     wait是等待 ,别人让你等待,并没说等待多长事件。别人用notify可以让你继续执行,不再等待。

 

 

运行状态

 

   正在执行的线程。

 

死亡状态

  当线程执行完,自动消亡。或调用stop方法消亡线程。

 

--------------------

可以获取和设置线程的名称。线程有默认的名称 是从0开始的。

Thread.currrent().getName 就可以获得线程的名称 也可以通过this方法获得线程的名称

Thread的构造方法中有一个含有参数的构造方法就是线程的名称  也可以通过setName方法设置线程的名称

---------------------

多线程买票

 

开启多线程卖100张票 就能产生一张票被多个线程卖

所以  把100张票设置成静态的 就可以解决问题。

但是控制台打印票的顺序到最后是132的原因是由双核cpu造成的

 

 

一个线程对象被多次启用,就会抛出线程非法异常。

跟运动员起跑类似,起跑时裁判员开枪,跑了一会又开枪,运动员不是疯了····

----------------------------

实现多线程的第二种方式  实现Runnable 接口

 

 

实现过程:

1.实现Runnable接口

2.实现run方法

3.创建Thread类的对象

4.Thread的构造方法中可以接收一个Runnable对象的参数

5.启动线程  thread对象.start

这时启动的不是Thread类中的空线程导入Run方法,而是实现了Runnable接口的run方法。

 

 

实现Runable接口和继承Thread的区别

1.java是单继承

2.run 方法所属不一样

runnable接口的好处。可以在使用线程的同时又能继承其他的类

----------------------------------

多线程的安全问题

 

比如卖票系统:当买到第0号票的时候  一个线程进了买票循环 没等到票数见一  另一个线程又进到了卖票循环 这样打票系统就会打出一张为0号的票  这是不符合实际的!

 

 

解决方法:一个线程卖完票后另一个线程才能执行其买票功能

     这里就可以用到同步代码块 synchronized(这个里面接受任意对象){

        需要同步的代码快

     }

-----------------------------------

同步:好处  可以解决线程安全问题

        不足: 线程每次执行的时候要判断是否锁旗标可以进入代码块

  使用地方: 1.必须要有两个以上线程

                   2.必须是共享的代码块

---------------------------------------

线程开启后 不一定马上执行

使用同步线程的时候注意是否用的锁旗标是一样的

静态同步方法的锁旗标不是this而是改类的字节码  A.class

 

 

 

单例有两种方式可以实现单例

1.饿汉模式

 

public class A{

     private static fianl A a = new A();

     private A(){}

     private static A  getAInstance(){

                return a;

     }

 

}

饿汉模式不会导致多线程的安全问题

2.懒汉模式

public class A{

      private static A a = null;

     private A(){

    }

    public static A getAInstance(){

              if(a==null){

                  a = new A();

              }else

                return a;

 

    }

 

}

分析:当开启两个线程1,和线程2.有中可能是线程1和线程2同时调用getAInstance 方法。

当线程1进了if方法后线程2也进了if方法,并不通事件都执行了 new A()所以在此可见单例被实例化了多次。导致安全问题发送。

解决方法:可以使用同步函数解决问题。但是同步函数有一定的缺陷。每次调用getAInstance的时候都要判断是否cpu把锁释放给改线程。

使用同步代买块和if嵌套可以解决问题,并切效率相对来说比较高。

 

if(a ==null){

  synchronized(obj){

    a  = new A();

     return a;

 

}

 

}else{

  return a;

}

 

经过代码的修改如上。只有当a为null的时候进入if代码块。判断是否拥有锁的权限。

 

------------------------------------

同步死锁的问题

如果有两个线程。进入a代码块 需要b代码块的锁。进入b代码块需要a代码块的锁。如果a.b两个锁不相互谦让。就出现死锁问题。

 

synchronized(a){

 

          

         synchronized(b){

       

 

          }

}

synchronized(b){

       

         

            synchronized(a){

       

 

               }

}

 

上图为模型

 

 

 


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3