黑马程序员----JAVA基础----函数与数组及多线程2

来源:互联网 发布:java 大数据搜索引擎 编辑:程序博客网 时间:2024/06/06 17:18

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

一、函数

1,函数的定义:函数是定义在类中的具有特定功能的一段独立小程序,又称为方法。

2,函数的格式:

修饰符返回值类型 函数名(参数类型形式参数1,参数类型 形式参数2,。。。){

执行语句;

return返回值;

}

注意1:当函数没有返回值时,返回值类型用void表示,函数体内的return语句可以不写。

如果写的话,后面不用加返回值,直接跟‘;’。

注意2:在return语句下面不能再有语句。

3,函数的特点:

a,定义函数可以将功能代码进行封装,可以方便对功能进行使用,提高了复用性。

b,函数只有在被调用时才会执行

在使用函数时,要明确函数的参数列表,要明确函数的返回值类型。

4,函数的一个重要特性:重载

在同一个类中,允许存在一个以上的同名函数,只要它们的参数列表不同即可。

参数列表包括参数个数、参数类型、参数顺序,有一项不同,函数就不同。

重载与返回值类型无关,只与参数名和参数列表有关。

Java是严谨性语言,如果函数出现调用的不确定性就会失败。

演示代码:

/* * 重载:同一个类中,允许存在一个以上的同名函数,只要它们的参数列表不同即可 */public class FunctionDemo {public static void main(String[] args) {}// 返回值:int  参数列表:2个,都是intprivate static int add(int a,int b){return a+b;}// 返回值:int  参数列表:3个,都是intprivate static int add(int a,int b,int c){return a+b+c;}// 返回值:int  参数列表:2个,都是doubleprivate static int add(double a,double b){return (int)(a+b);}// 返回值:double  参数列表:2个,都是int与上面的函数相同。// 虽然返回值类型不同,但函数名与参数列表相同,// java是严谨性语言,不允许这种形式存在//private static double add(int a,int b){//return(double)(a+b);//}}

二、数组

1,数组的概念:同一种类型数据的集合。

2,数组的好处:可以给数组中的元素进行编号,从0开始。方便操作这些元素。

3,数组的格式:元素类型[ ]数组名 = new  元素类型[元素个数或数组长度] 。

数组一旦建立,必须明确长度。演示代码:

/* * 数组的定义格式 */public class ArrayDemo1 {public static void main(String[] args) {// 数组定义时必须明确数组的长度<span style="white-space:pre"></span>,需要一个容器,但是不明确容器的具体数据int[] arr1 = new int[3];int arr2[] = new int[3];// 数组定义并初始化,不要在[]填写长度,存储已知具体数据int[] arr3 = new int[]{3,2,1};int arr4[] = new int[]{2,4,6,8};// 方式三静态初始化int[] arr5 = {33,44,55,66};}}

4,内存划分:寄存器、本地方法区、方法去、栈内存、堆内存

栈内存:存储的是局部变量。变量所属的作用域一旦消失,变量就会释放。

堆内存:存储数组和对象(数组也是对象),凡是被new出来的都在堆内存。

对内存的特点:a,每一个实体都有首地址值。b,对内存中每一个变量都有默认化初始值,

根据类型的不同而不同。整数--0,小数--0.0或0.0f,boolean--false,char--\u0000

c,对内存中的对象不用后会变成垃圾,java会自动回收垃圾(垃圾回收机制)。

5,数组使用过程中一些常见问题:

a,当访问一个数组中不存在的角标时,会引发角标越界异常:ArrayIndexOutOfBoundsException

b,当引用型变量没有任何指向时,还在用其操作实体,会引起NullPointerException

5,数组的基本操作:核心思想就是对角标的操作。

数组的基本操作包括存入、取出、获得最大(小)值、排序(升/降)、二分查找等,演示代码:

public class ArrayDemo1 {public static void main(String[] args) {show1();// 数组的存取show2();// 数组的最大值和最小值show3();// 选择排序show4();// 冒泡排序show5();// 二分查找}private static void show5() {int[] arr = new int[]{33,22,11,44,66,55};int index = binarySearch(arr,44);index = binarySearch2(arr,66);System.out.println(index);}private static int binarySearch2(int[] arr,int key){<span style="white-space:pre"></span>// 二分查找第二种形式int min,mid,max;min = 0;max = arr.length-1;while(min<max){mid = (min+max)>>1;if(key>arr[mid])min = mid+1;else if(key<arr[mid])max = mid-1;elsereturn mid;}return -1;}private static int binarySearch(int[] arr,int key) {int min,mid,max;min = 0;max = arr.length-1;mid = (min+max)/2;while(arr[mid]!=key){if(key>arr[mid])min = mid+1;else if(key<arr[mid])max = mid-1;if(min>max)return -1;mid = (max+min)/2;}return mid;}private static void show4() {int[] arr = new int[]{33,22,11,44,66,55};bubbleSort(arr);}/* * 冒泡排序 * 思路:遍历数组,第一轮:从第一个值(0角标)开始,与第二个值比较,如果第一个值 大于 * 第二个值,将二者位置交换,反之则不交换。然后用第二个值与第三个值比较,依次类推 * 当遍历到倒数第二个值时,就能确定最后一个值时数组中的最大值。 * 然后从头开始遍历,开始第二轮排序,此时不用考虑最后一个元素,这样额可以 * 确定倒数第二个角标的数值。 * 然后依次循环即可。 */private static void bubbleSort(int[] arr) {// 确定外循环的次数for(int i=0; i<arr.length-1; i++){// -1 避免角标越界// -i使内循环每次参与比较的值递减for(int j=0; j<arr.length-1-i; j++){if(arr[j]>arr[j+1]){int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}for(int i=0; i<arr.length; i++){System.out.print(arr[i]+" ");}}/* * 数组的排序(升序) * 思路:遍历数组,先将第一个值作为数组的最小值,将第一个值与第二值作比较, * 如果第一个值小于第二个值,那么位置不变,如果第一个值大于第二个值,那么 * 将这两个值的位置互换。然后用第一个值和第三个值比较,依次类推 * 通过一轮排序后,第一个数值已经是最小值,然后开始从第二个值开始比较,与 * 第一轮比较原理一致。通过比较可以确定第二位置的数值。 * 第三个、第四个。。。依次类推 * 当取到最后一个值时,不需要再判断 */private static void show3() {int[] arr = new int[]{33,22,11,44,66,55};selectSort(arr);for(int i=0; i<arr.length; i++){System.out.print(arr[i]+" ");}}/** * @param arr */private static void selectSort(int[] arr) {for(int i=0; i<arr.length-1; i++){for(int j=i+1; j<arr.length; j++){// 如果前一个值大于后一个值,将二者的位置调换if(arr[i]>arr[j]){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}}}/* * 取数组中的最大值 * 思路:定义一个变量记录最大值 * 遍历数组,先将第一个值默认为最大值,跟后面一个数值进行比较,如果第一个数大于第二个数值, * 那么最大值仍然是第一个数值,否则是第二个数值,依次类推,知道遍历完数组为止 */private static void show2() {int[] arr = {3,2,11,25,99,23,45};// 定义方法获取最大值。最小值思路一样int max = getMax(arr);System.out.println(max);}private static int getMax(int[] arr) {// 注意对max进行初始化时,应该将数组中的一耳光值赋值给maxint max=arr[1];// 遍历数组,当有值比max大时,就将这个值赋值给maxfor(int i=1; i<arr.length; i++){if(arr[i]>max)max = arr[i];}return max;}// 数组的存取private static void show1() {int[] arr = new int[5];// 对数组赋值for(int i=0; i<arr.length; i++){arr[i] = i;}// 将数组中的值取出for(int i=0; i<arr.length; i++){System.out.print("arr["+i+"]="+arr[i]+" ");}}}
6,进制转换:

思路(以16进制为例):将数字num与15进行&运算,得到最低4位的数值,再将该数值转换为

相应进制的数字即可,这个转换过程可以根据查表法来完成。然后将数字num右移4位(无符号

右移>>>),如果右移后的数字不为0,再与15进行&运算,依次类推。0为特殊情况,单独列出。

演示代码:

public class ArrayTest {public static void main(String[] args) {int num = 28;toBinary(num);toOctal(num);toHex(num);}private static void toHex(int i) {trans(i,15,4);}private static void toOctal(int i) {trans(i,7,3);}private static void toBinary(int i) {trans(i,1,1);}private static void trans(int num, int j, int k) {// 当num为0时,直接返回0if(num==0){System.out.println(num);return;}// 建立一个表,用于查询char[] chs = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};char[] arr = new char[32];int pos = arr.length;while(num!=0){int temp = num&j;arr[--pos] = chs[temp];num>>>=k;}for(int i=pos; i<arr.length; i++){System.out.print(arr[i]);}System.out.println();}}
7,二维数组
二维数组与一维数组大致相似,下面代码总结了格式及一些常见问题:

public class ArrayDemo2 {public static void main(String[] args) {show1();// 二维数组的定义show2();// 常见问题show3();// 二维数组遍历}private static void show3() {int[][] arr = {{2,3,4},{2,3},{5}};for(int i=0; i<arr.length; i++){for(int j=0; j<arr[i].length; j++){System.out.print(arr[i][j]+" ");}System.out.println();}}private static void show2() {int[][] arr = new int[3][2];// 二维数组System.out.println(arr);// 打印二维数组中角标为0的一维数组System.out.println(arr[0]);// 打印二维数组中角标为0的一维数组中0角标元素System.out.println(arr[0][0]);int[][] arr2 = new int[3][];// 二维数组System.out.println(arr);// 打印二维数组中角标为0的一维数组,打印结果为nullSystem.out.println(arr2[0]);// 打印二维数组中角标为0的一维数组中0角标元素,会抛出NullPointerException//System.out.println(arr2[0][0]);// 打印二维数组长度,其实就是一维数组的个数System.out.println(arr.length);// 打印二维数组中角标为1的的一维数组的长度System.out.println(arr[1].length);}private static void show1() {// 定义-int[][]arr1 = new int[3][2];int arr2[][] = new int[2][3];// 定义二int[][] arr3 = new int[][]{{1,2,3},{1,2}};int arr4[][] = new int[][]{{1,2,3},{1,2}};// 定义三int arr5[][] = {{1,2,3},{4,5},{6}};}}
三、多线程2

1,同步代码块对锁的操作是隐式的。

jdk1.5后,将锁封装成对象,提供了lock(获取锁)和unlock(释放锁)方法。

ReentrantLock,一个可重入的互斥锁Lock,它具有与使用synchronized相同的作用。

Lock接口:替代了同步代码块或者同步函数,将同步代码块的隐式锁操作变成显式操作。

同时更为灵活,可以在一个锁上加上多个监视器对象。

lock用来获取锁,unlock用来释放锁,通常需要定义在finally代码块中。

Condition接口:替代了Object中的wait、notify、notifyAll方法,将这些监视器方法进行单独

的封装,变成Condition监视器对象,可以任意锁进行组合。演示代码:

import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ThreadDemo10 {public static void main(String[] args) {// 创建公共资源的对象Duck d = new Duck();// 将该对象分别封装到生产和消费线程,再将消费或生产线程的对象作为Thread对象的构造函数// 的参数进行传递,并开启线程new Thread(new Producer(d)).start();new Thread(new Consumer(d)).start();new Thread(new Producer(d)).start();new Thread(new Consumer(d)).start();}}class Duck{private String name;private int count = 1;private boolean flag = false;// 创建锁对象Lock lock = new ReentrantLock();Condition pro = lock.newCondition();<span style="white-space:pre"></span>// 创建监视器对象Condition con = lock.newCondition();<span style="white-space:pre"></span>// 一个锁上可以绑上多个监视器对象public  void setDuck(String name){lock.lock();try{while(flag)try {pro.await();} catch (InterruptedException e) {e.printStackTrace();}this.name = name+count;System.out.println(this.name+"++++++++");count++;this.flag = true;// 使用notify,一次只唤醒一个线程,无法确保唤醒对方线程,如果唤醒本方线程,无意义con.signal();}finally{lock.unlock();}}public  void getDuck(){lock.lock();try{while(!flag)try {con.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(this.name+"--------");this.flag = false;pro.signal();}finally{lock.unlock();}}}// 将任务进行封装class Producer implements Runnable{// 将Duck进行封装,确保公共资源的唯一性private Duck duck;public Producer(Duck duck){this.duck = duck;}public void run(){while(true){duck.setDuck("烤鸭");}}}//将任务进行封装class Consumer implements Runnable{// 将Duck进行封装,确保公共资源的唯一性private Duck duck;public Consumer(Duck duck){this.duck = duck;}public void run(){while(true){duck.getDuck();}}}
2,wait和sleep的区别

a,wait可以指定时间也可以不指定时间,sleep必须指定时间

b,在同步中,对CPU的执行权和锁的处理不同,

wait:释放执行权,释放锁。sleep:释放执行权,不释放锁。

注意:在同步中,谁拿锁谁执行。其他线程可以是阻塞状态,但不能执行。

3,线程的停止:

a,使用stop方法。b,run方法结束。

怎么控制线程任务的结束呢?任务中都会有循环结构,只要控制住循环就可以结束任务。

控制循环通常用定义标记来完成。演示代码:

public class ThreadDemo11 {public static void main(String[] args) {// 创建任务对象,并传递给线程对象的构造参数StopThread st = new StopThread();new Thread(st).start();new Thread(st).start();// 当满足条件时,将flag置为falseint num = 1;for(int x=1; x<100; x++){if(x==50){st.setFlag();break;}System.out.println(Thread.currentThread().getName()+"......"+num++);}System.out.println("over");}}class StopThread implements Runnable{private boolean flag = true;public void setFlag(){flag = false;}@Overridepublic void run() {while(flag){//定义标记,从而可以结束循环结构System.out.println(Thread.currentThread().getName()+"......");}}}

但是如果线程处于了冻结状态(wait),无法读取标记,该如何结束?

在Thread类中提供了一个interrupt方法,将线程的冻结状态清除掉,让线程具有CPU的执行资格,

但是会抛出一个InterruptedException。

4,守护线程:setDaemon,在线程启动前使用,当正在运行的线程都为守护线程时,java虚拟机退出。

5,join方法:可以加入一个线程。setPriority方法:设置执行优先级,最低为1,最高为10,默认为5。

当线程优先级最高时,并不意味着该线程可以执行完才运行其他线程,依然要和其他线程抢执行权,只不过

运行到的概率提高。

public class ThreadDemo11 {public static void main(String[] args) throws InterruptedException {// 创建任务对象,并传递给线程对象的构造参数StopThread st = new StopThread();Thread t1 = new Thread(st);Thread t2 = new Thread(st);t1.start();t1.join();// t1线程要申请加入进来运行t2.start();// 优先级提高,默认优先级为5,最高位10,最低为1t2.setPriority(Thread.MAX_PRIORITY);for(int x=1; x<50; x++){System.out.println(Thread.currentThread().getName()+"......"+x);}System.out.println("over");}}class StopThread implements Runnable{private boolean flag = true;public void setFlag(){flag = false;}@Overridepublic void run() {for(int x=0; x<50; x++){System.out.println(Thread.currentThread().getName()+"......");}}}


The End










0 0
原创粉丝点击