黑马程序员_多线程和String类

来源:互联网 发布:淘宝店铺分销 编辑:程序博客网 时间:2024/05/16 11:18
------------- android培训、java培训、java博客、java学习型技术博客、期待与您交流! -------------

多线程

进程与线程进程是程序的一次动态执行过程,它经历了代码加载、执行到执行完毕整个过程,运行一个程序,就会启动一个进程,这时操作系统会为进程分配资源,最主要资源即内存空间;多进程操作系统指能同时运行多个进程(程序),每个进程随机获得CPU执行时间片。线程是比进程更小的执行单位,它是进程内部单一的顺序控制流;多线程是指一个进程中有多个线程同时运行,形成多条执行线索;它是实现并发机制的一种有效手段,目的是为了最大限度利用CPU资源。区别1、同为基本执行单元,线程是划分比进程更小的执行单位;2、每个进程都有一段专用的内存空间,但线程却共享内存单元(包括代码和数据),当有新线程产生,操作系统不分配新内存空间,而是让新线程共享原有进程的内存,因此线程间通信很容易,速度也很快。创建与启动线程的创建都是靠实现Runnable接口、复写run方法而来的,线程的启动却都是通过Thread类对象调用start方法,有以下两种方式:1、java中Thread类实现了Runnable接口,所以可直接定义类继承Thread,然后再将run方法复写,最后直接调用父类已有的start方法启动线程即可;2、定义类实现Runnable接口、复写run方法,将该类对象以多态形式传递给Thread对象,再通过Thread对象调用start方法。两者比较实现方式避免了java语言中单继承的局限性,方便应用;继承方式是将运行代码存储于子类run方法中,而另者是存储于Runnabl接口run方法中,继承方式一个对象只能调用一次start方法,因而如果想要多个线程运行它,则只能创建多个对象,如果创建了多个对象的话,则只能使其数据为共享数据。注意:run方法只是用于存储线程要运行的代码;start方法才能启动一个线程。Thread类构造函数Thread(Runnable target),多态,new新的Thread对象Thread(String name),new一个有名字的Thread对象方法String getName()   返回该线程名称static Thread currentThread()  返回当前执行线程对象的引用(选择性用this代替)static void sleep(long millis)  让当前执行线程暂休眠,另有异常抛出start()   使线程开执行,JVM开始调用该线程run方法interrupt()  将处于冻结状态的线程强制的恢复到运行状态,可与catch结合用作停止线程setDaemon  守护线程/用户线程/后台线程(线程.setDaemon(true))必须在线程启动前调用当所有的前台线程结束后,后台线程会自动结束,其它运行方式都一样toString()  输出线程名+线程级别+线程组setPriority  设置优先级,1-10级别,一般不写数字,用MAX(MIN NORM)_PRIORITY固定常量代表e.g:线程.setPriority(Thread.MAX_PRIORITY)static yield()  暂停当前正在执行的线程对象,并执行其它线程join() 当其它线程执行了此线程的.join()方法时,其它线程就会等待此线程执行完在执行线程状态1、执行状态2、结束/消亡状态3、冻结状态,sleep(long millis)、wait()让线程处于睡眠或等待即冻结状态4、阻塞/临时状态, 有执行资格但没有cpu执行权wait和sleep区别: wait:可以指定时间也可以不指定时间。不指定时间,只能由对应的notify或者notifyAll来唤醒。sleep:必须指定时间,时间到自动从冻结状态转成运行状态(临时阻塞状态)wait:线程会释放执行权,而且线程会释放锁,即其它线程可进入同步中执行;Sleep:线程会释放执行权,但不是不释放锁,即其它线程不可进入同步中执行另:wait()、notify()、notifyAll()在操作同步中线程时,都必须要标识他们所操作线程的锁,   同一个锁上的被等待线程,只可以被同一个锁上notify唤醒,即等待和唤醒必须是同一把锁   而锁是任意对象,所以可以被任意对象调用的方法需定义在Obeject类中线程安全多线程运行代码语句有操作共享数据,当一个线程操作了共享数据但没有执行完相应的后续操作,这时另一个线程获得CPU执行权继续操作共享数据再执行后续操作,就有可能导致错误。要解决这种隐患,则需要明确多线程执行代码中哪些语句操作了共享数据,然后保证同一时间只有一个线程执行这些操作共享数据的语句。线程同步同步代码块synchronized(对象){ 需同步语句 }  线程执行到该语句,都先进行判断,语句中没有线程则继续执行否则等待;另接受的对象可以自定义为任何对象,对象也就是锁;同步函数synchronized修饰的函数即同步函数函数需要被对象调用,都有一个所属对象引用,就是this,同步函数的锁也就是this同步前提1、必须要有两个或者两个以上线程2、必须是多个线程使用同一个锁同步死锁  通常将同步进行嵌套,就有可能出现。同步函数中有同步代码块,同步代码块中还有同步函数。两个窗口同时卖票,验证非静态同步函数所是this同理可将ticket变量用静态修饰,同步函数变为静态的来验证静态函数的锁是类名.class对象class Ticket implements Runnable{private int ticket = 100;boolean flag = true;public void run(){if(flag){while(true){//同步代码块synchronized(this){  //验证非静态同步函数是不是this,看所得票是否有误if (ticket>0){try{Thread.sleep(10);}catch(Exception e){}System.out.println(Thread.currentThread().getName()+"."+ticket--);}}}}elsewhile(true)method();}//同步函数public synchronized void method(){if (ticket>0){try{Thread.sleep(10);}catch(Exception e){}System.out.println(Thread.currentThread().getName()+":"+ticket--);}}}class Demo1{public static void main(String[] args){Ticket t = new Ticket();new Thread(t).start();try{Thread.sleep(10);}catch(Exception e){}//保证第一个线程进入到第一个循环里t.flag = false;  //让第二个线程进入第二个循环里new Thread(t).start();}}单例设计模式1、饿汉式class Single1{private static final Single1 s1 = new Single1();private Single1(){}public static Single1 getSingle1(){return s1;}}2、懒汉式class Single2{private static Single2 s2 = null;private Single2(){}public static Single2 getSingle2(){if (s2==null){synchronized(this){if (s2==null)return s2 = new Single2();}}return s2;}}线程间通信当多个线程在操作同一个资源,但是操作的动作却不一样时,就需要明确各个线程执行的先后顺序,这样线程间就有了通信。步骤1、将资源封装成对象。2、将线程执行的任务(任务其实就是run方法。)也封装成对象。3、通过等待+换新配合逻辑条件来操控各个线程的执行JDK1.5版本java.util.concurrent.locks.*;1、同步语句或函数用Lock锁接口替代;2、wait()、notify()、notifyAll被Condition接口中   await()、signal()、signalAll()替代注意这些方法需与各自锁搭档执行,所以都要定义在同步或锁中。见如下事例,多个线程生产和消费商品,生产1个消费1个;import java.util.concurrent.locks.*;class Resource{private String product;private int count =1;//锁旗标,实现不同操作线程依次交替执行private boolean flag=false;private Lock lock = new ReentrantLock();//一个锁上可有多个condition对象,从而可指定唤醒或等待某个线程private Condition condition_pro = lock.newCondition();private Condition condition_con = lock.newCondition();public void set(String product){lock.lock();try{//注意while与if的区别,while中线程唤醒会继续判断条件,if中却直接向下执行语句while (flag)condition_pro.await();this.product = product+count++;System.out.println(Thread.currentThread().getName()+"生产:"+this.product);flag = true;condition_con.signal();}catch(InterruptedException e){}finally{  //finally操作事例lock.unlock();//一定要有关闭或释放锁动作}}public void get() {lock.lock();try{while (!flag)condition_con.await();System.out.println(Thread.currentThread().getName()+"消费:  "+product);flag = false;condition_pro.signal();//指定唤醒线程}catch(InterruptedException e){}finally{lock.unlock();}}}class Producer implements Runnable{private Resource res;Producer(Resource res){this.res = res;}public void run(){while (true)res.set("商品-");}}class Consumer implements Runnable{private Resource res;Consumer(Resource res){this.res = res;}public void run(){while (true)res.get();}}class Demo2{public static void main(String[] args){Resource res = new Resource();Producer pro = new Producer(res);Consumer con = new Consumer(res);new Thread(pro).start();new Thread(pro).start();new Thread(con).start();new Thread(con).start();}}停止线程停止线程就是让线程运行的代码结束,即结束run方法;stop方法可以停止线程,但是已经过时;通常run方法里肯定定义循环。所以只要结束循环即可。1、定义循环标记(flag),通过改变循环标记,来控制线程循环;2、如果线程处于了冻结状态,是不可能读到标记的,这时就需要通过Thread类中的interrupt方法,   将其冻结状态强制清除。让线程恢复具备执行资格的状态,线程则可以读到标记,然后结束。线程简写1、new Thread(){public void run(){ 执行代码 }}.start();2、Runnable r = new Runnable(){public void run(){ 执行代码 }};new Thread(r).start();

String类

特点:一旦被初始化,就不能被改变。它既是一个对象,又是一个字符串常量。构造函数1、字节数组转字符串,可指定编码表解码String(byte[] bytes)String(byte[] bytes,int offset,int length,Charset charset)2、字符数组转字符串String(char[] value,int offset,int count)3、字符串缓冲区转字符串String(StringBuilder builder)方法1、获取1.1 字符串中包含的字符数,也就是字符串的长度int length(); (数组arr.length是属性没有括号)1.2 按指定角标获取字符char charAt(int index);1.3 按字符获取该字符在字符串中首次出现索引,若无返回-1int indexOf(int ch);  注意字符会自动按编码表转化成int型int indexOf(int ch,fromIndex);   指定起始位int indexOf(String str)   查字符串int indexOf(Strign str,fromIndex): 2、判断2.1 字符串中是否包含某一个字串boolean contains(CharSequence s)int indexOf(str)也可以用于对指定字符串判断是否包含e.g:if(str.indexOf("aa")!=-1)2.2 字符串中是否有内容boolean isEmpty();相当于判断length是否为0;2.3 字符串是否以自定内容开头boolean startsWith(str)2.4 字符串是否以自定内容结尾boolean endsWith(str);//刷选文件的时候是有用2.5 判断字符串的内容是否相同,复写了Object类中的equals方法boolean equals(str);//不忽略大小写2.6 判断内容是否相同,并忽略大小写。应用,密码大小写忽略。boolean equalsIgnoreCase();3、转换3.1 将字符串转成字符数组char[] toCharArray();3.2 将字符串转成字节数组byte[] getBytes(); //可以按照指定编码表转化3.3 将字符数组转成字符串,静态方法static String copyValueOf(char[])static String copyValueOf(char[] data;int offset,int count)static String valueOf(char[]);3.4 将基本数据类型转成字符串static String valueOf(基本数据类型 变量名)string.valueOf(3);相当于3+"";前者较专业    4、替换String replace(oldchar,newchar)  //记住先old后是newString replace(oldstr,newstr)  //替换字符串5、切割String[] split(regex)  //切割后为字符串数组6、获取子串String substring(int beginIndex);String substring(int begin,int end);//算头不算尾注意:end的最大值为str.length(),因为它不包括尾7、其它7.1 将字符串转成大写或者小写String  toUpperCase();String  toLowwerCase();7.2 将字符串两端的多个空格去除String trim();7.3 自然顺序的比较,复写了compareable比较方法int compareTo(String);从字符串第一字母开始比较,返回int数值StringBuffer字符串缓冲区,是一个容器,可以用于对数据进行修改,特点1、长度是可以变化的,数组也是容器但是长度是固定的,2、可以直接操作多个数据类型,数组一次只能操作一种类型3、最终会通过toString方法变成字符串,或String(StringBuffer sb)方法1、存储StringBuffer append(data)  将制定数据作为参数添加到已有数据结尾处StringBuffer insert(index,数据) 可以将数据插入到制定index位置2、删除StringBuffer delete(int start,int end):删除缓冲区中的数据,包含头不包含尾StringBuffer deletCharAt(index): 删除指定位置字符3、获取char charAt(int index)   获取指定角标字符int  indexOf(String str)int  lastIndexOf(String str)int  length()String substring(int start,int end)  返回String类型4、修改StringBuffer  replace(start,end,String str);void   setCharAt(index,char ch); //没有返回值5、反转StringBuffer reverse();6、将缓冲区中指定数据复制到指定字符数组中,void getChars(int srcBegin,int srcEnd,char[] des,int detBegin)字符串起始结束位置,目标数组,目标数组开始位置因为对数组的操作是有记忆的,所以返回类型为voidStringBuilder  JDK1.5版本后区别StringBuffer 是线程同步StringBuilder 是线程不同步以后建议使用后者,因为前者每次访问需要判断锁,效率相对较低,碰到多线程自定义锁。

基本数据类型包装类

格式  基本数据类型   引用数据类型byte              Byteshort             Shortint               Integerlong              Longboolean           Booleanchar              Character类型转换最常见操作就是基本数据类型和字符串类型之间的转换1、字符串类型转基本数据类型   基本数据类型 变量名 = new 引用数据类型.parse基本数据类型(String str);    e.g:int num = new Integer.parseInt("123");   或者通过 static intVlaue() 方法转换    new Integer("123").intValue();2、基本数据类型转字符串类型字符串类型 变量名 = 基本数据值+"" ;或, 引用数据类型.toString(int num);e.g:  Stirng str = Integer.toString(12);进制转换十进制转其它进制字符串表达形式   static String toBinaryString(int i)   static String toOctaryString(int i)   static String toHexString(int i)其它进制字符串转成十进制   static int parseInt(String ste,int radix);radix代表进制 新特性1、自动封装和自动拆箱    Integer x1 = 1 ; //自动封装成对象Integer x2 = x1 + 2 ; //先对象.intValue变成int数据进行运算后封装成对象注意x1可接收null,所以写代码时要注意判断,否则会出现空指针异常2、开辟空间Integer m1 = 128; Integer m2 =128; //m1 != m2Integer n1 = 127; Integer n2 =127; //n1 != n2方法1、equals, 比较两个对象数值是否相等2、compareTo,比较大小,后续集合中复写比较方法时候常用到

------------- android培训java培训、java博客、java学习型技术博客、期待与您交流! -------------
详情请查看:http://edu.csdn.net/heima/
0 0
原创粉丝点击