java: part i · using streams (java 8) •from java 8 onward we can convert collections to streams...

96
Java: part II Jef De Smedt Beta VZW 1

Upload: others

Post on 01-Aug-2020

21 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java: part IIJef De Smedt

Beta VZW

1

Page 2: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Course contents

• Java SE vs Java EE

• Enums

• Generics

• Collections

• Anonymous classes

• JDBC

• File Input/Output

• Multithreading

• Distributed systems

3

Page 3: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java SE vs Java EE

• Java Standard Edition• Core Java functionality: console applications, GUI (Windows Applications),

access to databases, low level networking

• Suited for Single machine applications and simple network applications

• Java Enterprise Edition• Extension to Java SE

• Client-Server applications: web applications (Servlet, JSP, JSF), important business layer

• Java Micro Edition• Older smartphones, not important anymore (no Android or IOS)

4

Page 4: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Enums

• An Enum is a type that is used when we have a limited number of values:

enum Season {SUMMER, AUTUMN, WINTER, SPRING};

• We can get all the values:

Season[] values = Season.values();

• We can convert from String to Season:

Season favorit = Season.valueOf(myseason.toUpperCase());

• We can convert from Season to int

int n = favorit.ordinal()

5

Page 5: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Generics

• New in Java 5

• Templates in C++ (not completely the same)

• Often used in collections

• Collection of Objects vs Collections of specific type

• ArrayList vs ArrayList<String>

• => add(Object) vs add(String)

6

Page 6: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Generics (generics01)

public class Main {

@SuppressWarnings("unchecked")

public static void main(String[] args) {

@SuppressWarnings("rawtypes")

ArrayList list1 = new ArrayList();

list1.add("Elvis"); // add a String

list1.add(42);// add a number

list1.add(new Person("Elvis", 42)); // add a person

for (Object o: list1) {

System.out.println(o);

}

}

}

7

Page 7: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Generics(generics02)

public class Main {

public static void main(String[] args) {

ArrayList<String> list1 = new ArrayList<String>();

list1.add("Elvis");

//list1.add(42); //not possible

//list1.add(new Person("Elvis", 42)); //not possible

for(String s:list1) {

System.out.println(s);

}

}

}

8

Page 8: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Generics(generics03)

• Create your own generic class Trap

public class Trap<E> {private E prisoner;public void catchPrisoner(E prisoner) {

this.prisoner = prisoner;}public E releasePrisoner() {

E tmpPrisoner = this.prisoner;this.prisoner = null;return tmpPrisoner;

}/*public String getPrisonerName() {* //impossible, not every class has a getName() method*return prisoner.getName();

}*/}

9

Page 9: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Generics(generics03)

• Use the class:public static void main(String[] args) {

Trap<Bear> bearTrap = new Trap<Bear>();

Bear baloo = new Bear("Baloo");

Duck donald = new Duck("Donald");

bearTrap.catchPrisoner(baloo);

Animal a = bearTrap.releasePrisoner(); //Animal is base class

System.out.printf("%s is released", a.getName());

//error: bearTrap cannot catch ducks

//bearTrap.catchPrisoner(donald);

}

10

Page 10: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Generics (generics04)

• Suppose we have classes Animal, Bear and Duck

class Animal{private String name;public Animal(String name) {

this.name = name;}public String getName() {

return name;}

}class Bear extends Animal{

public Bear(String name) {super(name);

}}class Duck extends Animal{

public Duck(String name) {super(name);

}}

11

Page 11: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Generics (generics04)

• Now we can create a Trap that only works with animals

public class AnimalTrap <E extends Animal> {private E prisoner;public void catchPrisoner(E prisoner) {

this.prisoner = prisoner;}public E releasePrisoner() {

E tmpPrisoner = this.prisoner;this.prisoner = null;return tmpPrisoner;

}public String getPrisonerName() {//Every prisoner is an Animal with a getName() method

return prisoner.getName(); }

}

12

Page 12: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Generics backward compatibility(generics05)

• Suppose we have a library that uses a non-generic ArrayList

• How can we use this in our (generic ArrayList) program?

• => @suppresswarnings(“unchecked”)

• Explanation: it would generate a compiler warning (not an error) because the compiler cannot assure the type safety. We simply suppress the warning

@SuppressWarnings("unchecked")

public static void main(String[] args) {

ArrayList<String> list = new ArrayList<String>();

Members members = new Members();

list.addAll(members.getMembers()); // public ArrayListgetMembers()

}

13

Page 13: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Generics “erasure”

• Java bytecode (compiled code) does not recognize generic types

• ArrayList<String> will be a simple ArrayList in bytecode => genericinformation is “erased” (hence “erasure”)

• Compiler will add the necessary casts to assure typesafety => e.g. list.add(s) might become list.add((String)s)

14

Page 14: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collections

• We have already seen an ArrayList in the previous examples

• An arraylist is an example of a collection (group of items)

• Java has different types of collections

• Collections form a hiërarchy in Java

15

Page 15: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

16

<<interface>Iterable

<<interface>Collection

<<interface>List

<<interface>Set

ArrayList LinkedList HashSet TreeSet

Ordered items with anindexed position

unique items, no indexed position

Page 16: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Iterable<E>/Iterator<E> interface(1)

• Iterable objects can be fetched one-by-one (“enumerated”)

• Iterable interface has one method: iterator() (returns Iterator)

• Iterator interface has three methods:• boolean hasNext() //checks whether there is a next

• T next() //fetches next item

• void remove() //removes current item

17

Page 17: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Iterable<E>/Iterator<E> interface(2)

• Typical usage:

Iterable<String> col = … // collection initialized here

Iterator<String> it = col.iterator();

while(it.hasNext()){

String s = it.next();

System.out.prinlnt()

}

18

Page 18: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection<E> interface

• Collections manage a group of items

• Among others it defines the following methods• boolean add(E item): add an item

• void clear(): removes all elements

• boolean contains(Object o): does the collection contain the object

• Iterator<E> iterator(): inherited from Iteratable interface

• boolean remove(object o): removes an object

• int size(): returns the number of items in the collection

• Object[] toArray(): returns the collection as an array

19

Page 19: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

List<E> interface

• A List is a Collection where each item has a position (just like an array)

• Among others it defines the following methods• boolean add(E items): inherited from Collection, adds an item to the end of the

collection• void add(int index, E item): insert an item at a position• E get(int index): returns the element at the specified position• int indexOf(Object o): returns the position of the first occurence of the object• Iterator<E> iterator(): inherited from Iteratable interface• int lastIndexOf(Object o): returns the position of the last occurence of the object• boolean remove(object o): removes an object• E set(int index, E item): replaces the item at the position• Object[] toArray(): returns the collection as an array

20

Page 20: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection01: using collections

Collection<String> building = new ArrayList<>();

building.add("Elvis");

if(building.contains("Elvis")) {

System.out.println("Elvis is in the building");

} else {

System.out.println("Elvis has left the building");

}

if (building.isEmpty()) {

System.out.println("The building is empty");

} else {

System.out.println("There is someone in the building");

}

21

Page 21: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection01: using collections and iterator

building.add("Priscilla");

Iterator<String> it = building.iterator();

while (it.hasNext()) {

String name = it.next();

System.out.println(name);

}

//When a class has an iterator, we can use a for each

for (String s: building) {

System.out.println(s);

}

building.clear();

22

Page 22: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Using streams (Java 8)

• From Java 8 onward we can convert collections to streams

• Streams can use lambda functions to manipulate data

• E.g.: .filter(e -> e.getDepartment().equals(“Accounting”))

23

e is an objectWhen this statement is true, the object goes to the next

step in the stream

Page 23: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection02: employee class

24

public class Employee {

private String name, department;

public Employee(String name, String department) {

this.name = name;

this.department = department;

}

public String getName() {

return name;

}

public String getDepartment() {

return department;

}

}

Page 24: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection02: main method

public static void main(String[] args) {

Collection<Employee> company = new ArrayList<Employee>();

company.add(new Employee("Elvis", "Entertainment"));

company.add(new Employee("Priscilla", "Accounting"));

company.add(new Employee("Colonel Parker", "Management"));

company.add(new Employee("Lisa Marie", "Accounting"));

//Java 8

company.stream()

.filter(e -> e.getDepartment().equals("Accounting"))

.forEach(e -> System.out.println(e.getName()));

}

25

For each object execute this statement

Page 25: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection03: set (unique items)

public static void main(String[] args) {

Set<String> items = new HashSet<String>();

items.add("Elvis");

boolean succeeded = items.add("Elvis"); // false

if (!succeeded) {

System.out.println("There is only one Elvis");

}

System.out.println("The set contains " + items.size() + " elements");

}

26

The set will contain 1 element

Page 26: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection04: unique objects?public static void main(String[] args) {

Set<Employee> items = new HashSet<Employee>();

items.add(new Employee("Elvis"));

boolean succeeded = items.add(new Employee("Elvis")); //true!!!

if (succeeded) {

System.out.println("There is an Elvis impersonator here");

}

Iterator<Employee> it = items.iterator();

while(it.hasNext()) {

Employee e = it.next();

if (e.getName().equals("Elvis")) it.remove();

}

System.out.println("The set contains " + items.size() + " elements");

}

27

Page 27: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection04: we must override the equalsmethod

public class Employee {

private String name;

public Employee(String name) {

this.name = name;

}

public String getName() {

return name;

}

28

This is not enough code to let a set check whether two employees are equal or not

Page 28: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection04: we must override the equalsmethod

@Override

public boolean equals(Object o) {

boolean equal = false;

if (o instanceof Employee) {

Employee e = (Employee)o;

equal = this.getName().equals(e.getName());

}

return equal;

}

@Override

public int hashCode() {

return name.hashCode();

}

29

My definition is: two employees are equal when they have the same name

When two objects are equal they must have the same hashcode

Page 29: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection05: listspublic static void main(String[] args) {

List<String> items = new ArrayList<String>();

items.add("Elvis"); // position 0

items.add("Colonel Parker"); // position 1

items.set(1, "Dries Van Kuijk"); // replace element 1

items.add("Vernon");

int index = items.indexOf("Elvis");

System.out.println("Elvis is on position " + index);

items.remove(1);

String name = items.get(1); //Vernon is shifted to position 1

System.out.println("On position 1 we have " + name);

ListIterator<String> it = items.listIterator(items.size());

while (it.hasPrevious()) {

System.out.println(it.previous());

}30

Page 30: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Collection06: mappublic static void main(String[] args) {

String[] words = {"one", "two", "one", "three", "three", "one"};

Map<String, Integer> frequency = new HashMap<String, Integer>();

for(String word: words) {

Integer freq = frequency.get(word);

if (freq == null) {

freq = 1;

} else {

freq = freq + 1;

}

frequency.put(word, freq);

}

System.out.println(frequency);

}

31

Page 31: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Anonymous classes

• Suppose we have an interface:

• Then we can define a class that implements the interface

32

interface Command{

void execute();

}

class MenuItem implements Command{

@Override

public void execute() {

System.out.println("Hi all");

}

}

Page 32: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Anonymous class

• And we can create an object of that class and use it

• But this class will only be used once, because it is a very specificmenu-item with a very specific command

33

MenuItem item1 = new MenuItem();

item1.execute();

Page 33: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Anonymous class

• As an alternative we can create a class “on the fly”

• The object is created based on a class that has no name (anonymousclass)

• We can use an anonymous class when the class will only be used once

34

Command item2 = new Command() {

@Override

public void execute() {

System.out.println("By all");

}

};

Page 34: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Anonymous class: Comparator interface

• We can sort a collection by using Collections.sort(collection):

Collections.sort(people);

• But as a second argument we can give a comparator object. A Comparator object has one method: compare(item1, item2)

• The method must return -1, 0, 1 when the first object is less than, equal to or greater than the second object

35

Page 35: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Anonymous class: Comparator interface

Collections.sort(people, new Comparator<String>() {

@Override

public int compare(String o1, String o2) {

return o1.substring(1).compareTo(o2.substring(1));

}

});

36

Page 36: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Lambda expressions

• When an interface only has one method(functional interface) it canbe written as a lambda function

Collections.sort(people,(o1, o2) ->

o1.substring(1).compareTo(o2.substring(1)));

• A lambda expression has • Arguments: (o1, o2)

• A lambda operator: ->

• A return value: o1.substring(1).compareTo(o2.substring(1)));

37

Page 37: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Lambda and streams

students.stream()

.filter(s -> s.getAge() >= 15 )

.sorted((s1, s2)->s1.getName().compareTo(s2.getName()))

.limit(2)

.forEach(s -> System.out.println(s));

//alternative: .foreach(System.out::println)

38

Get students with age>= 15

Sort them by name

Only take the first two

Print each one of them

Page 38: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java databases: jdbc

• To connect to a database we use a driver for the database

• Java Database Connection (JDBC) defines 4 driver types:• Type 1: a jdbc driver with a mapping to another protocol (mainly ODBC)

• Type 2: a jdbc driver with java code and native code (needs a native clientlibrary

• Type 3: a pure java client driver that connects to a middleware server withdatabase independent protocol

• Type 4: a pure java driver with database specific protocol

• Most popular databases have a Type 4 driver. (Oracle, MySQL, MSSQL, DB2, …)

39

Page 39: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java databases: derby

• From Java 7 onward javadb(a very simple database written in Java, not suited for production servers) is part of the Java Development Kit

• We can download the same database from apache derby (search forapache derby in google) : http://apache.cu.be/db/derby/db-derby-10.11.1.1/db-derby-10.11.1.1-bin.zip

• Unzip and put lib/derby.jar in the classpath of the application

40

Page 40: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java databases: 4 ways to run Derby

1. Embedded in memory: derby is started by the application, database is created in memory (database dropped when application stops)

2. Embedded in filesystem: derby is started by the application, database is created in the file system (database is stored in the file system between different invocations)

3. Network in memory: Derby is started separate from the application(can be shared between different applications), but database disappears after stopping Derby

4. Network in filesystem: Derby is started separate from the application, database is stored in the file system after derby is stopped

41

Page 41: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java databases: Derby connection strings

• Create embedded database in memory: jdbc:derby:memory:sample;create=true

• Create embedded database in file system: jdbc:derby:sample;create=true

• Connect to networked derby and create in memory database:jdbc:derby://localhost:1527/memory:sample;create=true

• Connect to networked derby and create database in file system:jdbc:derby://localhost:1527/sample;create=true

• If the database already exists: skip ;create=true

42

Page 42: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java databases: template

• To connect to a database we need a java.sql.Connection

• For that we use de getConnection factory method of java.sql.DriverManager:conn = DriverManager.getConnection(“jdbc:derby:memory:sample;create=true”); //inmemory embedded database

• We can use the same method to remove the database:DriverManager.getConnection("jdbc:derby:memory:sample;drop=true");

• This last command will cause an SQLException with SQLState “08006” (catch exception => is no error)

• We also need the library derby.jar (DERBY_HOME\lib\derby.jar)

43

Page 43: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java database: template (jdbc01)

• Resource protection block: whatever happens, connection must beclosed and database must be removed => try{…}finally{…}

Connection conn = null;

try{

conn =

DriverManager.getConnection("jdbc:derby:memory:sample;create=true");

System.out.println("Connected to database");

}finally{

if (conn != null) {

conn.close();

}

}

44

Page 44: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java database: alternative template (jdbc01bis)• Try-with-resources is exactly the same

try (Connection conn

=DriverManager.getConnection("jdbc:derby:memory:sample;create=true")){

System.out.println("Connected to database");

}

45

Page 45: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Derby network database (derbyclient.jar)

• To start the derby database useDERBY_HOME\bin\startnetworkserver.bat

• Add DERBY_HOME\lib\derbyclient.jar to the classpath of the project

• Create a connection object that creates the database (will issue warning, not error, when the database already exists)

• Create a statement object that can execute SQL statements

46

Page 46: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Create table: jdbc02

public class Main {

private static final String CONN = "jdbc:derby://localhost:1527/sample;create=true"

private static final String CREATEPERSON = "CREATE TABLE person (id intPRIMARY KEY, name VARCHAR(50))";

private static final String INSERTPEOPLE = "INSERT INTO person VALUES (1, 'Peter'), (2, 'Paul'), (3, 'Mary')";

public static void main(String[] args) throws SQLException {

try(Connection conn=DriverManager.getConnection(CONN);

stmt.executeUpdate(CREATEPERSON);

stmt.executeUpdate(INSERTPEOPLE);

}

}

}

47

Page 47: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Check whether table exists

• If the program does not give an error => table should be created

• We can check this with the ij-tool (DERBY_HOME\bin\ij.bat

C:\javadb\bin>ijij version 10.11ij> connect 'jdbc:derby://localhost:1527/sample';ij> select * from person;ID |NAME--------------------------------------------------------------1 |Peter2 |Paul3 |Mary

3 rows selectedij>

48

Page 48: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Using resultset: jdbc03

• A CREATE TABLE statement is a “fire-and-forget” statement => we do not need a result (except for an exception when the statement fails)

• A SELECT statement returns a result.

• statement.executeQuery(“….”) executes a query (SELECT)

• The returnvalue is a ResultSet

• A resultset can be compared to an inmemory table

• Advance to the next row in the table: ResultSet.next() (returns false ifat end of resultset)

• ResultSet.getXXX(columnNumber) returns the value of a “column”

49

Page 49: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Resultset: one value (jdbc03)

private static final String COUNT = "SELECT COUNT(*) FROM PERSON";

private static final String CONN = "jdbc:derby://localhost:1527/sample"

public static void main(String[] args) throws SQLException {

try(Connection conn= DriverManager.getConnection(CONN);

Statement stmt = conn.createStatement()){

try(ResultSet rs= stmt.executeQuery(COUNT)){

rs.next(); // go to the first (and only) row

//row contains one column with an integer

int number = rs.getInt(1);

System.out.printf("TABLE contains %d people\n", number);

}

}

}

50

Page 50: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Resultset with more values (jdbc03)

private static final String SELECT = "SELECT * FROM PERSON";public static void main(String[] args) throws SQLException {

try(…){ …

try(ResultSet rs = stmt.executeQuery(SELECT)){

while(rs.next()) {

int id = rs.getInt(1);

String name = rs.getString(2);

System.out.printf("%d: %s\n", id, name);

}

}

}}

51

Page 51: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Prepared statement (jdbc04)

• INSERT, UPDATE and DELETE statements can be executed with the executeUpdate() method.

• But these statements often contain a static and an dynamic part:• Delete from person where id=1

• Delete from person where id=2

• …

• A database can compile the static part (prepare) and execute the statement with different dynamic parts

• For this we use a prepared statement

52

Page 52: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Prepared statement(jdbc04)

private static final String CONN ="jdbc:derby://localhost:1527/sample";

private static final String INSERT = "INSERT INTO PERSON (id, name) VALUES (?,?)";

public static void main(String[] args) throws SQLException {

Person[] persons = {new Person(4,"Elvis"), new Person(5, "Lisa Marie")};

try(Connection conn = DriverManager.getConnection(CONN)){

try(PreparedStatement prepstmt = conn.prepareStatement(INSERT)){

for(Person p:persons) {

prepstmt.setInt(1, p.getId()); // first ?

prepstmt.setString(2, p.getName()); // second ?

prepstmt.executeUpdate();

}

}

53

Page 53: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Autonumbering fields (jdbc05)

• In Derby we create a table with an autonumbering field with the following SQL statement:private static final String CREATE = "CREATE

TABLE products (id int generated always as

identity primary key, name varchar(50), price

decimal)";

• The database will provide the value for ID => no insert ID:private static final String INSERT = "INSERT

INTO products (name, price) VALUES (?, ?)";

54

Page 54: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Autogenerated keys (jdbc05)

• We ask to return the generated keys in prepareStatement• getGeneratedKeys returns a resultset with the keyspstmt = conn.prepareStatement(INSERT, PreparedStatement.RETURN_GENERATED_KEYS);pstmt.setString(1, "Pencil");pstmt.setBigDecimal(2, new BigDecimal(10));pstmt.executeUpdate();rs = pstmt.getGeneratedKeys(); // get generated idif (rs.next()) {int id = rs.getInt(1);System.out.printf("Pencil added with key %d\n",

id);

55

Page 55: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Rowsets

• The capabilities of a resultset depend on the capabilities of the driver

• Some drivers let you create scrollable resultset (scroll back and forth)

• Rowset add this extra capability to drivers that do not support thisnatively (JdbcRowset)

• We can also use CachedRowsets that let you work without a connection to the database

56

Page 56: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

JdbcRowset(jdbc06)

• A JdbcRowset can be constructed from a Connection

• Using a JdbcRowset we can scroll backward in a tableconn = DriverManager.getConnection("jdbc:derby://localhost:1527/sample");

jdbcRs = new JdbcRowSetImpl(conn);

jdbcRs.setCommand(SELECT);

jdbcRs.execute();

jdbcRs.last(); // goto last row in rowset

while (!jdbcRs.isBeforeFirst()) {

int id = jdbcRs.getInt(1);

String name = jdbcRs.getString(2);

System.out.printf("%d: %s\n", id, name);

jdbcRs.previous();

}

57

Page 57: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

JdbcRowset(jdbc07)

• A JdbcRowset can also be constructed from a connectionstring

• A JdbcRowset is updateable: we can insert a row (we have to move to the insertrow first)

• Adding new values is done by using the updatexxx() methods

• The insert in the database is done with insertRow()jdbcRs = new JdbcRowSetImpl();

jdbcRs.setUrl("jdbc:derby://localhost:1527/sample");

jdbcRs.setCommand(SELECT);

jdbcRs.execute();

jdbcRs.moveToInsertRow();

jdbcRs.updateInt(1, 4);

jdbcRs.updateString(2, "Elvis");

jdbcRs.insertRow();

jdbcRs.moveToCurrentRow();// move back to the row we were on

58

Page 58: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

JdbcRowset: update and delete

• Updating values in a Rowset is comparable to inserting rows

• We do not have to move to the insertrow, the current row is updated

• After updating the currentrow we have to call updateRow() to writethe new values to the database

• We can cancel the changes by calling cancelRowUpdates() (instead of updateRow())

• To delete a row we call deleteRow(): the current row is deleted in the database.

59

Page 59: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

CachedRowset

• A JdbcRowset only works when there is an (open) connection to a database.

• A CachedRowset copies the values from the database to an in-memory table

• We can change the values in the in-memory table

• Afterwards we can copy the changes to the database (acceptChanges())

• To update the right rows in de database the rowset has to know the unique key for every row (setKeyColumns())

60

Page 60: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

CachedRowset(jdbc08)

• We define a CachedRowset with a command and a definition of the unique columns (because we also want to update)crs = new CachedRowSetImpl();

crs.setCommand("SELECT * FROM person");

crs.setKeyColumns(new int[] { 1 }); // Define primary keys

• Next we can read the data, for this we need an open connection

• After reading we can close the connectionprivate static void readData(CachedRowSet crs) throws SQLException{

try(Connection conn = DriverManager.getConnection(CONN) ) {

crs.execute(conn);

}

}

61

Page 61: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

CachedRowset(jdbc08)

• We do not need an open connection to change the dataprivate static void doubleName(CachedRowSet crs) throws SQLException {

for (crs.first(); !crs.isAfterLast(); crs.next()) {

String name = crs.getString(2);

name = name + name;

crs.updateString(2, name);

crs.updateRow(); //does not write to the database

}

}

• This updates the in-memory table, in the database nothing is changed(yet)

62

Page 62: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

CachedRowset(jdbc08)

• To write the changes to the database we need an open connection

• The method acceptChanges() writes all the changes to the databaseprivate static void writeData(CachedRowSet crs) throws

SQLException,SyncProviderException {

try(Connection conn = DriverManager.getConnection(CONN)) {

crs.acceptChanges(conn);

}

}

• The method acceptChanges() can throw a SyncProviderExceptionwhen the underlying data has changed

63

Page 63: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

CachedRowset: optimistic concurrency

• Rows in a database are not locked while a CachedRowSet is used

• => value in database may be changed by another user while someoneis using the CachedRowSet = conflict

• The method acceptChanges will throw a runtimeException when a conflict arises: SyncProviderException

• Optimistic concurrency: “special” update statementUPDATE person SET name=‘PeterPeter’ WHERE id=1 AND name=‘Peter’

• The value is only updated when the database record has not changedin the meantime

64

Page 64: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

CachedRowset: optimistic concurrency(jdbc09)• We start with catching the exception:try {crs = new CachedRowSetImpl();crs.setUrl("jdbc:derby://localhost:1527/sample");crs.setCommand("SELECT * FROM person");crs.setKeyColumns(new int[] { 1 });crs.execute();System.out.print("Hit <RETURN> key");scanner.nextLine(); // change data in database (ij-tool)doubleName(crs);crs.acceptChanges();

} catch (SyncProviderException ex) {resolveConflict(crs, ex);

} finally {if (crs != null)crs.close();

}

65

Page 65: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

CachedRowset: optimistic concurrency(jdbc09)• A SyncResolver is a rowset with a row for every update that did not

succeed

• We go to the next row with nextConflict()

• Because we want to show the value in the rowset we also positionthe cachedrowsetprivate static void resolveConflict(CachedRowSet crs,

SyncProviderException ex) throws SQLException {

SyncResolver resolver = ex.getSyncResolver();

while (resolver.nextConflict()) {

int row = resolver.getRow(); //get rownumber

crs.absolute(row); // goto to conflicting row in CachedRowSet

66

Page 66: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

CachedRowset: optimisticconcurrency(jdbc09)• Rows that were not updated because they were after the conflicting row get a value of null for

conflictValue

switch (resolver.getStatus()) {case SyncResolver.UPDATE_ROW_CONFLICT:String nameInRowSet = crs.getString(2);Object nameInDataBase = resolver.getConflictValue(2);if (nameInDataBase != null) {System.out.printf("No update: %s(rowset) vs %s(db)\n",

nameInRowSet, nameInDataBase);} else {System.out.printf(

"%s not updated because of previous errors", nameInRowSet);}break;

case SyncResolver.INSERT_ROW_CONFLICT:case SyncResolver.DELETE_ROW_CONFLICT:System.out.println("Other conflict");break;

}

67

Page 67: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Internationalisation

• Internationalisation (I18N) is the process to “internationalise” applications

• That means:• Show labels, menus, … in the right language

• Show numbers and dates in the right form

• Sort according to the right collation

• Translations in java can be provided• As text file (properties)

• In a special java class

68

Page 68: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Internationalisation: properties files

• Example of a properties file for English(MessageBundle.properties)greetings = Hello.

farewell = Goodbye.

inquiry = How are you?

• The same file for French and Dutch(MessageBundle_fr.properties andMessageBundle_nl.properties)greetings = Bonjour.

farewell = Au revoir.

inquiry = Comment allez-vous?

greetings = Goedendag.

farewell = Tot ziens.

inquiry = Hoe gaat het met u?

69

Page 69: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Internationalisation(international01)

• We load a bundle for the right localepublic static void main(String[] args) {//Locale currentLocale = Locale.FRENCH;//Locale currentLocale = new Locale("nl");Locale currentLocale = new Locale(“de");// getBundle(basename, locale) loads the right locale file// if the file is not available (German), it will use the // default locale of the system and the corresponding properties // file. If the corresponding properties file for the default // locale of the systemi s not available, the base file is used //(MessageBundle.properties)ResourceBundle messages =

ResourceBundle.getBundle("MessageBundle",currentLocale);

System.out.println(messages.getString("greetings"));

System.out.println(messages.getString("inquiry"));System.out.println(messages.getString("farewell"));}

70

Page 70: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Internationalisation with classes (international02)• Instead of a properties file we can also use an object that returns the

key-value pairs

• The object must be of type ListResourceBundlepublic class MyBundle extends ListResourceBundle {

private Object[][] contents = {{"greetings",

"Hello"},{"farewell", "Goodbye"},{"inquiry", "How are

you?"}};

@Override

protected Object[][] getContents() {

return contents;

}

}

71

Page 71: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Internationalisation withclasses(international02)• The name of the class determines the locale

• French-Belgium:public class MyBundle_fr_BE extends ListResourceBundle {…}

• Dutch-Belgiumpublic class MyBundle_nl_BE extends ListResourceBundle {…}

• Usage of the bundle is the sameResourceBundle messages =

ResourceBundle.getBundle("org.betavzw.MyBundle",currentLocale);

72

Page 72: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Internationalisation: number and date formatting(internation03)• We can define a numberformatter to format integers and doubles:NumberFormat formatter =

NumberFormat.getNumberInstance(currentLocale);

String doubleOutput = formatter.format(pi);

String intOutput = formatter.format(answer);

• We can define a dateformatter to format dates:DateTimeFormatter dateFormatter = DateTimeFormatter

.ofLocalizedDate(FormatStyle.SHORT).withLocale(currentLocale);

LocalDate date = LocalDate.of(1935, Month.JANUARY, 8);

String dateString = dateFormatter.format(date);

73

Page 73: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Internationalisation: messageformatting(international03)• We can combine string and number/date formatting by defining a

messageformat:private Object[][] contents = {…{"MESSAGE_Format","PI c''est {0, number}.\n{1, number} est la réponse.\nElvis est né le {2, date, short}"},};

• Using braces we choose the position of the argument and the type (number, date)

74

Page 74: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Internationalisation: collation/sorting(international04)• A Collator has a compare() method to compare two strings according to a

locale:private static Collator collator = Collator.getInstance(Locale.FRANCE);public static void main(String[] args) {List<String> strings = new ArrayList<String>();strings.add("péché");strings.add("pêche");…Collections.sort(strings, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {

return collator.compare(o1, o2);}

});for(String s: strings) {System.out.println(s);

}

75

Page 75: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java I/O streams

• An I/O stream represents an input source or an output destination

• E.g.: file, network socket, memory arrays, …

• In this chapter we take a look at file streams

• The name “stream” comes from the fact that we read (or write) a stream of bytes

• Java defines different kinds of streams: bytestreams (read/write per byte/8bits) characterstreams (read/write per unicode character)

76

Page 76: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java buffered I/O streams

• Reading (or writing) per byte or per character is not very efficient

• A buffered stream reads a number of bytes/characters from a streamin a buffer and flushes (writes) the buffer to the stream

• A buffered stream uses the decorator design pattern: its constructorneeds a character or byte stream:BufferedReader reader = new BufferedReader(new FileReader("a.txt"));

• When we read from a BufferedReader the reader reads from the underlying stream to fill the buffer. All subsequent read-operations come from the buffer until the buffer is empty and new data is read from the stream again.

77

Page 77: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java PrintWriter/Stream(FileIO01)

• A PrintWriter writes to a character stream

• A PrintStream writes to a bytestream

• System.out is an example of a PrintStream

• Println(), Print() and Printf() are typical PrintWriter/PrintStreammethods

78

Page 78: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java PrintWriter(fileIO01)

• When we use a file we should always close the filestream

Scanner scanner = new Scanner(System.in);

try(PrintWriter writer = new PrintWriter(new

FileWriter("out.txt"))) {

String line;

System.out.println("Give line (end with empty line)");

while(!"".equals(line = scanner.nextLine())) {

writer.println(line);

}

System.out.println("<TERMINATED PROGRAM>");

}

79

Page 79: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Java BufferedReader(fileIO02)

• We read the file we have written in the previous exampletry(BufferedReader reader = new BufferedReader(new

FileReader("../fileIO01/out.txt"))){

String line;

while ((line = reader.readLine()) != null) {

System.out.println(line);

}

}

• (in fact System.out is also a BufferedReader)

80

Page 80: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Writing objects(fileIO03)

• We can dump(write) objects to streams, provided they are Serializable

• In order to be Serializable they must implement the Serializableinterface

• In order to implement Serializable the class can only contain primitivetypes or other Serializable member variables:public class Person implements Serializable {

private static final long serialVersionUID = 1L;private String name;private int age;…

}

81

Page 81: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Writing objects(fileIO03)

• Using an ObjectOutputStream and the writeObject() method we canstream objects:ArrayList<Person> persons = new ArrayList<Person>();

persons.add(new Person("Elvis", 79));

persons.add(new Person("Priscilla", 69));

try (ObjectOutputStream out = new ObjectOutputStream(new

FileOutputStream("persons.bin"))){

out.writeObject(persons);

System.out.println("<Program terminated>");

}

82

Page 82: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Reading objects(fileIO04)

• When we know which objects are available we can read them from anObjectInputStream (using the right cast and the right SerialVersionUID in the Person class):List<Person> persons = null;

try(ObjectInputStream in = new ObjectInputStream(new

FileInputStream("../fileIO03/persons.bin"))){

persons = (List<Person>)in.readObject();

for (Person p: persons){

System.out.printf("%s: %s\n", p.getName(), p.getAge());

}

}

83

Page 83: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Multithreading(concurrency)

• A console application has one thread of execution: all statements are executed in sequence.

• We can start a second thread of execution: statements can beexecuted in parallel.

• Multithreading can improve the responsiveness of a program: executing long running tasks in a separate thread while the mainthread processes the user commands. (GUI programs)

• Multithreading is often used in server applications (multiple clientsare handled in parallel)

• Multithreading can complicate a computer program.

84

Page 84: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Multithreading: thread states

85

New

Ready

Running

Terminated BlockedWait/Sleep

start()

dispatched by Operating SystemTime slice expired

End thread

I/O operation

I/O completed

sleep()join()lock

notify()Other thread has stoppedDone sleeping

Page 85: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Multithreading: multithread01

• Code that has to be executed must be in a method

• Method must be part of class that extends Thread or implementsRunnable

• Interface Runnable contains one method: run()

• Because a thread can be interrupted, the run()-method must catch the InterruptedException

86

Page 86: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Multithreading: multithread01

• We define a class that implements Runnable

public class ThreadRunner implements Runnable {private String name;public ThreadRunner(String name) {

this.name = name;}@Overridepublic void run() {

try {for (int i = 0; i < 5; i++) {

System.out.println("Running " + name);Thread.sleep(1000);

}} catch (InterruptedException e) {// InterruptedException when an another thread interrupts this thread

e.printStackTrace();}

}

}

87

Page 87: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Multithreading: multithread01

• First we execute the run()-methods in sequence

• Then we execute them in different threads

public static void main(String[] args) {ThreadRunner tr1 = new ThreadRunner("TR1");ThreadRunner tr2 = new ThreadRunner("TR2");System.out.println("Both 'threads' run in main thread");tr1.run();tr2.run();System.out.println("Both 'threads' run in different thread");Thread t1 = new Thread(new ThreadRunner("TR1"));Thread t2 = new Thread(new ThreadRunner("TR2"));t1.start(); //invokes run() method from Runnablet2.start();System.out.println("End of program (will end before TR1 and

TR2)");

}

88

Page 88: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Multithreading: multithread02

• Concurrent threads can interfere with each other when they update the same value at the same time

• AtomicInteger can solve this problem

atomicCounter.incrementAndGet();

• This is an atomic operation: both actions (increment and get) happen as one operation

89

Page 89: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Multithreading: threadpools

• Until now there was a one-to-one relationship between task(run() method) and thread => for every task a new thread had to be created+ the thread was destroyed after the task was finished

• But: thread creation is an expensive operation for an operating system

• A threadpool contains a number of threads.

• When we give a task to a threadpool one of the free threads is usedto execute the task.

• When there is no free thread: task waits in a queue

• Task is finished => thread becomes a free thread again

90

Page 90: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Multithreading: threadpools(multithread03)

• An executor is responsible for the execution of tasks by a threadpool

• In this example we create an executor for a fixed thread pool (fixednumber of threads)

int processors = Runtime.getRuntime().availableProcessors();System.out.printf("Number of processors: %d\n", processors);

ExecutorService e = Executors.newFixedThreadPool(processors);

• We can create a list of task objects (implement Callable interface) andinvoke them using invokeAll (waits until all tasks have finished)

List<ParallelBlur> tasks = new ArrayList<ParallelBlur>();

…e.invokeAll(tasks);

91

Page 91: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Distributed programs

• Java EE (Enterprise Edition) is more suited for distributed systems

• Distributed system has server (listening) and client (connecting) components

• A server socket listens on a port, a client socket connects to a port

• Data between client and server is exchanged by using streams (cfrfiles)

92

Page 92: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Server socket(chatserver)

• A server socket blocks until a client connects

• In a real application (multiple clients) we will start a new thread toprocess the client requests

ServerSocket socket = null;

Socket client = null;

BufferedReader in = null;

PrintWriter out = null;

try {

//listen to port 8888 on localhost

socket = new ServerSocket(PORT, 0, InetAddress.getByName(null));

System.out.println("Waiting for connection...");

client = socket.accept();

93

Page 93: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Server socket (chatserver)

• We define a BufferedReader and a PrintWriter to read and write

• For the PrintWriter we set autoflush to true: a println() writes to the stream

//define socket reader and socket writer

in = new BufferedReader(new

InputStreamReader(client.getInputStream()));

out = new PrintWriter(client.getOutputStream(), true);

System.out.println("I have a client");

String line=null;

Scanner scanner = new Scanner(System.in);

94

Page 94: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Server socket(chatserver)

• Read and write data, in the end we close the sockets//read until client closes socketwhile (null != (line = in.readLine())){

System.out.println(line);System.out.print("Input: ");String answer = scanner.nextLine(); // read answer from

server userout.println(answer); //write answer to client

}} finally {

if (client != null && !client.isClosed()){client.close();

}if (socket != null && !socket.isClosed()) {

socket.close();}

}

95

Page 95: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Client socket(chatclient)

• A client connects to a port on a certain machine

• We define a reader and a writer

Socket client = null;PrintWriter out = null;BufferedReader in = null;try {

//Connect to server on port 8888 on localhostclient = new Socket(InetAddress.getByName(null), PORT);//define socket reader and writerout = new PrintWriter(client.getOutputStream(),true);in = new BufferedReader(new

InputStreamReader(client.getInputStream()));Scanner scanner = new Scanner(System.in);String line;System.out.print("Input: ");

96

Page 96: Java: part I · Using streams (Java 8) •From Java 8 onward we can convert collections to streams •Streams can use lambda functions to manipulate data •E.g.: .filter(e -> e.getDepartment().equals(Accounting))

Client socket(chatclient)

• And then we start writing and reading//send until user enters 'bye‘while (!"bye".equals(line = scanner.nextLine())) {

out.println(line); // write line to serverString answer = in.readLine(); // read line from serverSystem.out.println(answer);System.out.print("Input: ");

}} finally {

if (out != null) out.close();if (in != null) in.close();if (client != null && !client.isClosed()) {

client.close();}

}

97